How to use #MockBean without having to #Inject the Bean again? - unit-testing

Is there a more concise / elegant way to reach this functionality in Micronaut?
#MicronautTest
class ControllerTest {
#Inject
#field:Client("/")
lateinit var client: RxHttpClient
#Inject
lateinit var redeemService: RedeemService
#MockBean(RedeemService::class)
fun redeemService(): RedeemService = mockk {
every { validate(any()) } returns true
}
#Test
fun test() {
// some logic triggering a call to redeemService
verify(exactly = 1) {
redeemService.validate("123")
}
}
}
To me it looks like redundant work to have to declare the #MockBean and then also having to #Inject the previously declared #MockBean.
From what I remember, in Spring Boot this is just an annotation on a lateinit var.
Did I misunderstand or overlook something?

You need the mock bean, for replacing the service and inject it everywhere in your application .. if you want to do some verification you eighter have to inject it back or create instance within your class and return that with the mock bean
private val redeemService: RedeemService = mockk {
every { validate(any()) } returns true
}
#MockBean(RedeemService::class)
fun redeemService() = redeemService

Usually, MockBean are NO-OP collaborators that are intended to be DI-ed into dependent beans instead of relying on concrete bean implementations.
If within a test fixture ~ your tested feature scope ~ you have to verify collaborator calls or provide custom response to other collaborators calls, then you have to inject it.
This may seem, as stated, like redundancy but it's not and it SHOULD be done in such a way otherwise Micronaut (or any other framework doing so) would have a little design flaw.
Relying on custom implementations (annotations in this case) to act as bean providers and injection points within tests would result in non-deterministic behavior and internal tight-coupling to framework specificities as you will be injecting your dependencies in your test fixture differently from the way you'll be doing it in your actual application code, and that should be avoided.
In short, if your bean (mock or concrete) make it to the your test implementation through the #Inject annotation, then you are assured it will work the same when injected into real application code since a test fixture is a bean itself.

Related

spy on mocked object accessor (get and set)

Mocking out dependencies while testing angular components. ComponentA injects ServiceA, I want to mock serviceA in my test
class ServiceA {
private _prop = 1;
get prop (): number {
return this._prop;
}
set prop(p: number) {
this._prop;
}
}
class ComponentA {
private injectedService: ServiceA;
constructor(private injectedService: ServiceA) {
this.injectedService = injectedService;
}
method () {
this.injectedService.prop = this.injectedService.prop + 1;
if (this.injectedService.prop === 5) {
this.injectedService.prop = 1;
}
}
}
With the above program structure it is important to have a serviceA mock that has accessor(getter and setter for injectedService.prop) implementation, since a part of the program is dependent on the value of injectedService.prop that was prior set.
Options that I have tried:
ts-mockito: ts-mockito mocks does not have access type set. With this limitation ts setter won't be recognised. A workaround would be to define actual methods to 'set' and 'get' and call these methods. setter would still need a more workaround as below:
// default get stub
when(mock.getProp()).thenReturn();
// setter redefines get stub
when(mock.setProp(anything())).thenCall((p) => {
when(mock.getProp()).thenReturn(a);
});
typemoq:
static mock calls constructor, big flaw when target mock class as other dependency injection(s)
dynamic mock conditions like (this.injectedService.prop === 5) will never be truthy beacuse this.injectedService.prop (i.e mock.object.prop) points to a function. On this I feel there could be a way that I'm yet to figure out, I would appreciate any help
(Personal preference) I prefer jasmine spyOn to typemoq verify for assertions on my mocks. This could be ignored if not possible.
Things I don't want to do
I do not want to modify classes to be mocked except to add standard typescript accessors
I do not want to create an Interface/Class off classes to be mocked just for the purpose of creating a mock for test
Although I'm open to compromise on above if there is a good justification or standard
I would also appreciate if anybody could direct me to code base(s) that has proper test and follows standard if any.
Note: I'm testing an angular app with karma + jasmine ... but all these doesn't count as I am merely creating class from constructor, no Testbed just simple typescript class unit-test.

How to decide what to mock in Java Unit Tests?

I am trying to write a Unit Tests to a legacy code using Mockito.
But I am not able to understand how do I mock it. Can some please help.
The real problem I am facing is actually I am not able to decide how to make a decision on what exactly is to be mocked? Below is the code. I have looked at numerous videos on YouTube and read many Mockito Tutorials but all of them seem to be guiding mostly about how to use the Mockito Framework.
The basic idea of what to Mock is still unclear. Please guide if you have a better source. I do understand that the code showed below does not really showcase the best coding practice.
public class DataFacade {
public boolean checkUserPresent(String userId){
return getSomeDao.checkUserPresent(userId);
}
private SomeDao getSomeDao() {
DataSource dataSource = MyDataSourceFactory.getMySQLDataSource();
SomeDao someDao = new SomeDao(dataSource);
}
}
Well, a Unittest, as the name implies, tests a unit. You should mock anything that isn't part of that unit, especially external dependencies. For example, a DAO is normally a good example for something that will be mocked in tests where the class under tests uses it, because otherwise you would really have actual data access in your test, making it slower and more prone to failure because of external reasons (for example, if your dao connects to a Datasource, that Datasource's target (for example, the database) may be down, failing your test even if the unit you wanted to test is actually perfectly fine). Mocking the DAO allows you to test things independently.
Of course, your code is bad. Why? You are creating everything in your method by calling some static factory method. I suggest instead using dependency injection to inject the DAO into your facade, for example...
public DataFacade(SomeDao someDao) {
this.someDao = someDao;
}
This way, when instantiating your DataFacade, you can give it a dao, which means, in your test you can give it a mock, for example...
#Test
public void testSomething() {
SomeDao someDaoMock = Mockito.mock(SomeDao.class);
DataFacade toTest = new DataFacade(someDaoMock);
...now you can prepare your mock to do something and then call the DataFace method
}
Dependency injection frameworks like Spring, Google Guice, etc. can make this even easier to manage, but the first step is to stop your classes from creating their own dependencies, but let the dependencies be given to them from the outside, which makes the whole thing a lot better.
You should "mock" the inner objects that you use in your methods.
For example if you write unit tests for DataFacade->checkUserPresent, you should mock the getSomeDao field.
You have a lot of ways to do it, but basically you can make getSomeDao to be public field, or get it from the constructor. In your test class, override this field with mocked object.
After you invoke DataFacade->checkUserPresent method, assert that checkUserPresent() is called.
For exmaple if you have this class:
public class StudentsStore
{
private DbReader _db;
public StudentsStore(DbReader db)
{
_db = db;
}
public bool HasStudents()
{
var studentsCount = _db.GetStudentsCount();
if (studentsCount > 0)
return true;
else
return false;
}
}
And in your test method:
var mockedDb = mock(DbReader.class);
when(mockedDb.GetStudentsCount()).thenReturn(1);
var store = new StudentsSture(mockedDb);
assertEquals(true,store.HasStudents());

Mock an Eureka Feign Client for Unittesting

i am using spring cloud's eureka and feign to communicate between some services (lets say A and B). Now id like to unittest my service layer of a single service (A). The problem is, that this service (A) is using a feign client to request some information of the other service (B).
Running the unittests without any special configuration throws the following exception: java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: service-b => but i do not want any server to run.
My question is: Is there a way to mock the feign client, so i can unittest my service (A) without running an eureka instance and service (B)?
Edit:
I ended up creating a stub for the feign client. The stub is marked as a primary component to force spring instantiating the stub within my tests.
This is the solution i came up with.
//the feign client
#FeignClient("user")
public interface UserClient {
UserEntity getUser();
}
//the implementation i use for the tests
#Component
#Primary //mark as primary implementation
public class UserClientTestImpl implements UserClient {
#Override public UserEntity getUser() {
return someKindOfUser;
}
}
The question is ... do you even need to mock? I often see that people mention "mock" as the first solution to anything that "should not be part of the unit test". Mocking is a technique, not the solution to everything. (see here).
If you are still at the early stages of your code, just refactor and use something else instead of depending on the concrete instance of the Feign Client. You might use an interface, an abstract class, a trait or whatever you want. Don't depend on the object itself, otherwise you have to "mock it".
public interface IWebClient {
public String get(...);
public String post(...);
}
To the question: but I will have other code that will do exactly the same (except that it will be on the concrete instance of Feign), what do I do then?
Well, you can write a functional test and call an instance of a web server that you can setup locally - or use Wiremock, as mentioned by Marcin Grzejszczak in one of the answers.
public class FeignClientWrapper implements IWebClient {
private feign = something
public String get() {
feign.get( ... )
}
public String post() {
feign.post( ... )
}
}
Unit tests are used to test algorithms, if/else, loops: how units work. Don't write code to make mocks fit - it must be the other way around: your code should have less dependencies, and you should mock only when you need to verify the behavior (otherwise you can use a stub or a fake object): do you need to verify the behavior? Do you need to test that a particular method gets called in your code? Or that a particular method gets called with X, Y, and Z for 3 times in a row? Well, then yes, mocking is ok.
Otherwise, use a fake object: what you want is to test just the call/response and maybe the status code. All you probably want is to test how your code reacts to different outputs (e.g., the field "error" is present or not in a JSON response), different status codes (assuming that the Client documentation is right: 200 OK when GET, 201 when POST, etc).
Mocking a feign client is really useful in microservice component tests. You want to test one microservice without having to start all the other microservices.
If you're using Spring (and it looks like you are), the #MockBean annotation together with a bit of Mockito code will do the job.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment =
SpringBootTest.WebEnvironment.DEFINED_PORT)
public class TestYourComponent {
#Configuration
#Import({YourConfiguration.class})
public static class TestConfiguration {
}
#MockBean
private UserClient userClient;
#Test
public void someTest()
{
//...
mockSomeBehavior();
//...
}
private void mockSomeBehavior() {
Mockito.doReturn(someKindOfUser).when(userClient).getUser();
}
}
If you need to use a mock you can use Wiremock to stub the response for a given request - http://wiremock.org/stubbing.html. That way you will do integration tests with real HTTP requests sent. For unit testing the answer from #Markon is very good.

How to test JSF bean methods that use session parameters?

I'm having a hard time trying to implement unit tests on my JSF backing bean classes... For instance some of the methods use session or request parameters, obtained using this sort of code:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("paramKey");.
My question is: how can I test a method which obtains values from the session or request?
What I usually do is to avoid calling static methods into the beans I want to test. That implies your current code to be refactored:
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get("paramKey");
Are there ways to test them with their static method calls? Probably there are, but they led me to a lot of trouble more than help. So at the end I got rid of them and changed my design. Just let a second bean do it (which you'll mock later). In your case, create a #SessionScoped bean which manages that functionality:
#ManagedBean
#SessionScoped
public class SessionBean{
public Object getSessionParam(String paramKey){
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get(paramKey);
}
}
And inject that bean in every single bean that needs it (I usually extend my view/request beans from an abstract bean which has it, so don't have to implement it in every single bean):
#ManagedBean
#RequestScoped
public class RequestBean{
#ManagedProperty(value="#{sessionBean}")
private SessionBean sessionBean;
public void accessSessionParam(){
sessionBean.getSessionParam("name");
}
}
That way you can access static methods easily, via your auxiliary SessionBean. Then, how to test it? Just create a mock of it (using Mockito, for instance):
public class Test{
public void test1(){
SessionBean sb = Mockito.mock(SessionBean.class);
//Mock your 'getSessionParam' method
ValueBean vb = new ValueBean();
Mockito.when(sb.getSessionParam(Mockito.anyString()).thenReturn(vb);
//Create your bean to test and set your mock to it
RequestBean rb = new RequestBean();
rb.setSessionBean(sb);
//here you can test your RequestBean assuming
//sessionBean.getSessionParam()
//will return vb for every single call
}
}
It is possible to mock FacesContext but this is less than ideal. Mockito example:
import javax.faces.context.FacesContext;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public abstract class ContextMocker extends FacesContext {
private ContextMocker() {}
private static final Release RELEASE = new Release();
private static class Release implements Answer<Void> {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE)
.when(context)
.release();
return context;
}
}
If your platform supports it, prefer CDI to JSF managed beans. CDI has static dependency checking and injects proxies to prevent scope leak. CDI doesn't support all of JSF's features but it is relatively easy to connect JSF managed beans to CDI where necessary.
JSF managed beans restrict the scope that you inject types into but even that can lead to scope leaks. For example, the #{sessionScope} variable can be injected into a session scope bean even though the object belongs to the request scoped ExternalContext. It is possible to overcome this by writing your own JSF bean proxies.
Note: most of this was written with Java EE 6 in mind; things might have improved with Java EE 7.

How do I use PowerMock / Mockito / EasyMock to use a mocked object for dependency injection?

I have an AuthenticationManager.authenticate(username,password) method that gets called in someMethod of a SomeService under test. The AuthenticationManager is injected into SomeService:
#Component
public class SomeService {
#Inject
private AuthenticationManager authenticationManager;
public void someMethod() {
authenticationManager.authenticate(username, password);
// do more stuff that I want to test
}
}
Now for the unit test I need the authenticate method to just pretend it worked correctly, in my case do nothing, so I can test if the method itself does the expected work (Authentication is tested elsewhere according to the unit testing principles, however authenticate needs to be called inside that method) So I am thinking, I need SomeService to use a mocked AuthenticationManager that will just return and do nothing else when authenticate() gets called by someMethod().
How do I do that with PowerMock (or EasyMock / Mockito, which are part of PowerMock)?
With Mockito you could just do that with this piece of code (using JUnit) :
#RunWith(MockitoJUnitRunner.class)
class SomeServiceTest {
#Mock AuthenitcationManager authenticationManager;
#InjectMocks SomeService testedService;
#Test public void the_expected_behavior() {
// given
// nothing, mock is already injected and won't do anything anyway
// or maybe set the username
// when
testService.someMethod
// then
verify(authenticationManager).authenticate(eq("user"), anyString())
}
}
And voila. If you want to have specific behavior, just use the stubbing syntax; see the documentation there.
Also please note that I used BDD keywords, which is a neat way to work / design your test and code while practicing Test Driven Development.
Hope that helps.