Getting Missing 1 invocation to... in - java

I have a test that is testing a Spring #Service class. This service class autowires in a dao #Repository. The dao also autowires in a class to provide extra functionality. I would like to mock the calls in the dao so I have something like so:
#DisplayName("Tests for ...")
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MyServiceTest
{
#Injectable
TheRepository myDao;
#Tested(fullyInitialized = true)
TheService myServiceUnderTest;
#Nested
#Tag("...")
#DisplayName("Tests for method: ...")
class TestClassContainer {
#Test
public void test1() {
IAnalysisDataScenario data = new CommonAnalysisDataScenario();
new Expectations() {{
myDao.nameExists(anyString); result = data.mockedNameExists();
...
}};
Map<String, Object> result = myServiceUnderTest.getAnalysis(data.getName(),data.getId());
assertTrue(!result.isEmpty());
}
}
}
The call to getAnalysis in the service calls the dao method nameExists which I want to return the result from mockedNameExists in the Expectations block but I can't figure out what I'm doing wrong.
This is what I see when I run the test:
Missing 1 invocation to:
...dao.impl.TheRepository#nameExists(any String)
on mock instance: ...dao.impl.TheRepository#61230f6a
Caused by: Missing invocations
at ...dao.impl.TheRepository.nameExists(TheRepository.java)

I see what the issue is in this case. The error message now makes sense. In this particular test, the method that is missing the invocation is not actually called because of the code path the test takes based on the the parameters. So the Expectations block must only contain mocking behavior for code that actually WILL BE EXECUTED. Now I understand

Related

Getting NullPointerException while calling nested method of Service class using mockito

I am writing JUnit test cases for my Service classes.
I have created dummy data to understand my scenario.
#Service
MainClass {
#Autowired
C c;
public void someServiceMethod(){
ResultClass someResult = c.getResult(string,string, int, int, List<String>,boolean);
}
}
#Service
public class C {
#Autowired
SomeRepository someRepository;
public ResultClass getResult(string,string, int, int, List<String>,boolean){
ABC returnSomeClassObject = someRepository.getSomeData(String,int,int);
}
}
#Test
MainClassTest {
#MockBean
SomeRepository someRepository;
when(someRepository.getSomeData(anyString(),anyInt(),anyInt())).thenReturn(SomeRepository);
//calling MainClass method
MainClass.someServiceMethod();
}
Class C's getSomeData() method returning ABC class object which is NULL and latter setting into another same class type object.
After setting value I am getting NULLPointerException as ABC is NULL.
Anybody have any idea where I am going wrong?
You are not returning expected object while writing mock statement
#Service
public class C {
#Autowired
SomeRepository someRepository;
public ResultClass getResult(string,string, int, int, List<String>,boolean){
ABC returnSomeClassObject = someRepository.getSomeData(String,int,int);
//Your return type should be ResultClass
// Where your return statement
// What is ABC?
}
}
#Test
MainClassTest {
#MockBean
SomeRepository someRepository;
when(someRepository.getSomeData(anyString(),anyInt(),anyInt())).thenReturn(SomeRepository);
// Why are you returning SomeRepository, This Should return object of ABC
#MockBean
ABC mockResultClass
when(someRepository.getSomeData(anyString(),anyInt(),anyInt())).thenReturn(mockResultClass);
//calling MainClass method
MainClass.someServiceMethod();
}
You are calling MainClass.someServiceMethod() which in turn calls getResult of class C. You should be mocking class C and using when-thenReturn on getResult() of C class if your intention is to test someServiceMethod() of Main class. Autowired will not work here since this is a Unit test and hence the instance of C c in Main class will be null.
Something like below:
#MockBean
C c;
when(c.getResult(anyString(), anyString(),anyInt(),anyInt(), any(List.class), anyBoolean()).thenReturn(someResult);
c.getResult(string,string, int, int, List<String>,boolean);
So, first of all, we need to be clear on what exactly you are unit testing. If you are trying to unit test someServiceMethod inside of MainClass, then that means you should NOT be also testing the functionality of someRepository. The idea is that each unit test should only be testing just that, a unit of code. So, to do that we need to use stubs as stand-ins for what would actually happen when you call methods owned by other classes. Then, we would write a differrent unit test just for someRepository.getSomeData() to confirm that it is also working as intended. In this manner, when get an error later down the line we will know exactly where we are encountering an issue.
Another issue I see is there is an apparent mismatch of return types for getResult() in C. The method says it returns a ResultClass, but when you call getSomeData you are expecting an ABC object. Either you left out the details where you convert the object back to a ResultClass, or that is a mistake. I'm going to assume the former unless you say otherwise.
With that in mind, let's write our test. Here's how I would write the test:
#RunWith(SpringRunner.class)
public class MainClassTest {
#Mock
C c;
#InjectMocks
MainClass mainClass;
#Test
public void testSomeServiceMethod {
ResultClass resultClass = new ResultClass(); //relevant constructor details here, mockbean, etc. you get the idea
//set any desired data for resultClass here
Mockito.when(c.getResult(anyString(), anyString(),
anyInt(), anyInt(), any(List.class), anyBoolean()))
.thenReturn(resultClass);
ResultClass newResult = mainClass.someServiceMethod();
//relevant test assertions here
}
}
As you can see, we are creating a ResultClass in the test, and telling Mockito to return that when getResult is called instead of what you would normally expect it to return. While the functionality may seem limited now, this is preferred as we only testing the MainClass and not the rest of our method calls.
In addition to this, we can (and should) write tests for getResult in C, and getSomeData in SomeRepository. I will leave it to you to write those tests.
EDIT: accidentally posted a bit early, fixing now.

Test class with nested dependencies

I'm testing a class with nested (Autowired) dependencies. The class implements businesslogic for making alterations in the backend. Specifically the test should assert that when a certain backend call returns an error:
No more backend calls are made
The response object returns an error
I dont know how the do the latter.
My class looks something like this:
public class Handler {
#Autowired
private DaoImpl dao;
#Autowired
private SpecificUtil util1;
#Autowired
private GeneralUtil util2;
#Autowired
private Helper helper;
public Response doSomethingClever(Request request) {
// calls to dao
// logic with help of util and helper classes
}
}
The testclass:
public class HandlerTest {
#Spy
private DaoImpl dao;
#Mock
private SpecificUtil util1;
#Mock
private GeneralUtil util2;
#Mock
private Helper helper;
#InjectMocks
Handler handler;
#Test
public void testDoSomethingClever() {
// set up dao to fail
QueryResult error = getErrorResult();
org.mockito.Mockito.when(dao.queryBackEnd(any(SpecificQuery.class))).thenReturn(error);
// perform query
Request request = getTestRequest();
Response errorResponse = handler.doSomethingClever(request);
// verify that either:
// Response has errors - fails
// because helper classes are mocks, have not set the error
assertNotNull(response.getErrorMessage());
// the method setErrors of Response was called once - fails
//because the setError was called earlier!
Response spyResponse = Mockito.spy(errorResponse);
verify(spyResponse, times(1)).setError(anyString);
//verify no other calls are made except the queryBackEnd call - this part works
org.mockito.Mockito.verify(dao).queryBackEnd(any(SpecificQuery.class));
org.mockito.Mockito.verifyNoMoreInteractions(dao);
}
}
The Response object is created in the Handler class. If i check the returned response, no interactions will be recorded by Mockito, because the interactions have taken place prior to calling Mockito.spy.
I have tried making it an integration test, by using #Spy instead of #Mock. The idea is to instantiate all the nested dependencies except for the dao and get a proper Response to test for errors. But this does not work because some of the #Autowired helper and utility classes also have #Autowired dependencies and these nested dependencies are not instantiated during testing.
Is there any way to inject #Spy objects into other #Spy objects with Mockito?
Or is there some other solution in this case? Sould i write my own mockobjects?
A unit test should test the code of a specific unit only (here the Handler class). This includes interacting with the dependencies.
From what you wrote in your question and comments your handle method looks something along these lines:
public class Handler {
#Autowired
private DaoImpl dao;
#Autowired
private Util util;
public Response doSomethingClever(Request request) {
SpecificQuery specificQuery = new SpecificQuery();
specificQuery.setSomeData(request.getSomeData());
IntermidiateResponse intermidiateResponse = dao.queryBackEnd(specificQuery);
Response response = util.processIntermidiateResult(intermidiateResult);
return response;
}
}
There are a few interactions to unit test here:
Given a Request instance assert that DaoImpl::queryBackEnd method is called with a SpecificQuery instance that has someData property set to someData property from the Request object
Given a mocked IntermidiateResponse being returned from the DaoImpl::queryBackEnd method assert that this result is passed on to the Util::processIntermidiateResult method
Given a mocked Response being returned from the Util::processIntermidiateResult method assert that this is exactly what gets returned from the handle method
This way you have 100% coverage on the Handler::handle method. If you have some more calls in the response processing pipeline you test them all accordingly.
Hope this answers your question. Good luck
There are two options, one is to test the Handler in isolation, mocking everything else. See the answer by jannis. The other option is to control/mock the in- and output of the Handler, and treat the Handler and all its utility classes as a black box.
I have opted for this last option because it means that i can refactor the utility-classes, and the Handler class itself, and that tests will succeed as long as i don't change what the Handler does. It does mean that i have departed somewhat from doing unit testing and that i'm really doing more of an integration test.
For this i mock the Dao class, so that i can have it return an error at the desired point and so that i can assert that no further calls are made after the error.
It is the only class i mock, so i need to inject it into the Handler. This is possible with Springs ReflectionTestUtils (I did'nt know about this yesterday)
The testcode then becomes shorter:
public class HandlerTest {
#Autowired
private Handler handler;
#Test
public void testDoSomethingClever() {
// set up dao to fail
Dao mockDao = org.mockito.Mockito.mock(DaoImpl.class);
QueryResult error = getErrorResult();
org.mockito.Mockito.when(dao.queryBackEnd(any (SpecificQuery.class))).thenReturn(error);
// inject the dao
ReflectionTestUtils.setField(handler, "dao", mockDao);
// perform query
Request request = getTestRequest();
Response errorResponse = handler.doSomethingClever(request);
// verify that Response has errors
assertNotNull(response.getErrorMessage());
//verify no other calls are made except the queryBackEnd call
org.mockito.Mockito.verify(dao).queryBackEnd(any(SpecificQuery.class));
org.mockito.Mockito.verifyNoMoreInteractions(dao);
}
}

Mock not used with #Secured

My mocks are not being picked up when I add a #Secured to any method in the service class and test the service class. This even happens when I am testing a method that isn't secured. I don't understand whether it is due to the mock not being used or being overriden.
public class Service {
#Autowired
private DAO dao;
public void method1() {
...
//System.out.println("DEBUG:" + dao.hashCode());
dao.XXX();
...
}
#Secured("...") // added second time (Case 2)
public void method2() {
...
dao.XXX();
...
}
}
public class ServiceTest {
#Mock
private DAO dao;
#InjectMocks
#Autowired
private Service service;
#Before
public void beforeTest() {
MockitoAnnotations.initMocks(this);
}
public void testMethod1() {
Mockito.when(dao.XXX()).thenReturn(...);
//System.out.println("DEBUG:" + dao.hashCode());
...
}
public void testMethod2() {
Mockito.when(dao.XXX()).thenReturn(...);
...
}
}
Case 1:
I test method1 (testMethod1) without the #Secured on method2 and everything works fine. My expected results match what the Mock dao returns.
Case 2
I add the #Secured to method2 and re-run testMethod1. The test completes but the results are not matching the Mock dao. The actual dao has been used and the actual results match the database data.
I use the DEBUG statements to print the hashcode of the dao in the ServiceTest class and the Service class. In Case 1 they are the same. In Case 2 they are different.
Apparently there is something happening when I add the #Secured. I want to know what that is.
Assuming you are using the SpringJUnit4ClassRunner, the difference may be that Spring is creating a Proxy around your Service to handle the #Secured annotation, and Mockito cannot handle the injection of the dao in the proxy.
Btw, the same would happen with #Asynchronous, #Transactional and co.
I would suggest to use the MockitoRunner (forget Spring), or, if you really need to combine Spring and Mockito, use springockito

How to mock a method call within a method for which i am writing junit test

Could someone help me with mocking a method call within a method
my code is like :
public class Service {
public List<Bean> Filter(Bean bean){
List<Bean> Filtered_List = getUtilityService.getBeanList();
//Do something
return beanList;
}
}
Now i want to write test case for Service class . How can i mock :
List Filtered_List = getUtilityService.getBeanList(); and set values in it.
The clean solution is to extract UtilityService to a field and pass a mock to the constructor.
public class Service {
private UtilityService utilityService;
public Service(UtilityService utilityService) {
this.utilityService = utilityService;
}
public List<Bean> Filter(Bean bean){
List<Bean> filteredList = utilityService.getBeanList();
//Do something
return beanList;
}
}
You can also introduce a UtilityServiceFactory and have a utilityServiceFactory field in the Service.
public class Service {
private UtilityServiceFactory utilityServiceFactory;
public Service(UtilityServiceFactory utilityService) {
this.utilityServiceFactory = utilityServiceFactory;
}
public List<Bean> Filter(Bean bean){
List<Bean> filteredList = utilityService.create().getBeanList();
//Do something
return beanList;
}
}
If getUtilityService is located in Service class, there is also a dirty solution: partial mock. But I do not recommend it. It's better to refactor your code and use one of previous approaches.
EDIT:
Constructor injection with #InjectMocks is not the best idea but here you are:
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
//other imports
#RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
#Mock
UtilityService utilityService;
#InjectMocks
Service service = new Service(null);
#Test
public void shouldFilterBeans() throws Exception {
//given
given(utilityService.getBeanList()).willReturn(asList(new Bean()));
//when
List<Bean> result = service.filter(new Bean());
//then
assertThat(result).hasSize(1); //probably you want to check something else
}
}
to test a method including its own parameter and return value, like the Filter method in your code, it's enough to just pass a Bean instance to it, and then assert the returned List<Bean> object equals to your expected result. generally, for this kind of method, i think it's no need to use mock frameworks.
but if you really want to test the getUtilityService().getBeanList() method call, you should refactor your code:
addfield UnitilityService service and its corresponding setter method in your class Service
in your unit test code, inject a mocked service using the setter method to the object under test and given a returning value for its getBeanList() method, then invoke your Filter method, finally, verify the method call. for the detailed implementation, you can refer the answer of #woru.

Java: How do I mock a method of a field when that field isn't exposed?

I'm using Java 6, JUnit 4.8.1, and writing a console application. My application has a member field that isn't exposed …
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
private void initServices() {
…
m_oppsSvc = new OpportunitiesServiceImpl(…);
}
...
}
I want to mock a behavior such that whenever one method from my service is called, (e.g. m_oppsSvc.getResults()), the same result is always returned. How do I do that? There's no setter method for the field. I'm currently working with Mockito 1.8.4. Is it possible to do this with Mockito or some other mock framework?
This is what you want:
#RunWith(MockitoJUnitRunner.class)
public class MyAppTest {
#Mock private OpportunitiesService mocked_m_oppsSvc;
#InjectMocks MyApp myApp;
#Test public void when_MyApp_uses_OpportunititesService_then_verify_something() {
// given
given( mocked_m_oppsSvc.whatever()).willReturn(...);
// when
myApp.isUsingTheOpportunitiesService(...);
// then
verify...
assertThat...
}
}
Using: Mockito 1.9.0, BDD style, FEST-Assert AssertJ.
Hope that helps :)
Given that you're already using mockito, why not just use reflection:
#RunWith(MockitoJUnitRunner.class)
public class MyApp {
#Mock
private OpportunitiesService m_oppsSvc;
private MyApp myApp;
#Before
public void before() throws Exception {
myApp = new MyApp();
Field f = MyApp.class.getDeclaredField("m_oppsSvc");
f.setAccessible(true);
f.set(myApp, m_oppsSvc);
}
}
It's a bit ugly, but it will do the trick. Note that this may not be the most efficient way to do it with Mockito, but it will work.
There's also Powermock which should allow you to do this as well using the Whitebox class. I won't get into the whole details of Powermock but here's the call to inject the private field value, which should be a mock object:
Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);
You should consider attempts to mock a private field a smell. That is, a sign that either what you're trying to do is either incorrect or that your code is currently structured incorrectly. You should only need to mock public methods or injected dependencies
In the code you've given you should consider injecting OpportunitiesService as follows:
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
public MyApp(OpportunitiesService oppsSvc) {
this.m_oppsSvc = oppsSvc;
}
...
}
In your test you can then inject a mock as follows:
OpportunitiesService mockOpportunitiesService =
Mockito.mock(OpportunitiesService.class);
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue);
MyApp app = new MyApp(mockOpportunitiesService);
You can easily do it with JMockit:
public class MyAppTest
{
#Tested MyApp myApp;
#Test
public testSomething(final #Capturing OpportunitiesService mockService)
{
new NonStrictExpectations() {{
mockService.getResults(); result = asList("a", "b", "C");
// record other expectations, if needed
}};
myApp.whateverMethodIWantToTest();
new Verifications() {{
mockService.doSomething(anyInt);
// verify other expectations, if needed
}};
}
}
Even though the implementation class OpportunitiesServiceImpl isn't mentioned in test code, its instances (any number of them) will still get properly mocked.
Generally you should use dependency injection and pass the mock object (of type OppportunitiesServiceImpl) in via the constructor, a separate setter or directly to the method (getResults). You might need to extract an interface for OpportunitiesServiceImpl first.
Usually, this is solved through the use of dependency injection. In regular (production) mode, your dependency injection container (e.g. Spring or Guice) will inject an instance of OpportunitiesService into MyApp through your constructor or through a setter.
Then, when you're testing you can "inject" a mock instance manually using the same setter or constructor argument.
Instead of doing
m_oppsSvc = new OpportunitiesServiceImpl(…);
Try Passing OpportunitesService in through MyApp's constructor

Categories

Resources