mockito stub makes no difference to test result? - java

I'm new to Mockito and working on a basic example below. If I comment out the stubbed line below the test still passes, what am I doing wrong?
I would have expected the test to fail if I remove the stubbed line as the 'serviceUnderTest' would then not return the correct result from the underlying call to the 'doSomething' method in the mocked dependency?
public class MyTest {
private MyService serviceUnderTest;
#Mock
private MyHelper mockedDependency;
#Before
public void doBeforeEachTestCase()
{
MockitoAnnotations.initMocks(this);
serviceUnderTest = new MyServiceImpl();
serviceUnderTest.setMyHelper(mockedDependency);
}
#Test
public void test1()
{
try
{
SomeObject someObject = null;
// create my stub
stub(mockedDependency.doSomething("123", false, false)).thenReturn(someObject);
// run the implementation
ServiceResult serviceResult = serviceUnderTest.anotherMethod("123", false, false);
// check the state
assertNotNull(serviceResult);
// check the behaviour of the mock
verify(mockedDependency).doSomething("123", false, false);
}
catch(Exception e)
{
fail();
}
}
}

At the time you do your stubbing, someObject is null. So you're setting up the mock to return null from that method.
But null is the default value that a mock will return anyway, from a method that returns an object. Your stubbing actually makes no difference. Note that there are some exceptions to this rule.
If a method returns a collection, then the default return will be an empty collection.
If a method returns one of the wrapper types, then the default return will be zero or false, rather than null.
The toString method returns the name of the mock.

Turns out it was my own misunderstanding of Mockito!
The test was always passing because of the irrelevance of the stubbed method in this case. The stubbed method is used to provide a response to a method call in the service under test, it does not mean that the actual method that I'm verifying at the end of the test is not called.
The method I'm verifying is called in the service under test and the stub makes no difference to this, hence it passes.

At first, if it's a pure unit test you can get rid of #Before section using #RunWith and #InjectMocks annotations. They will handle the initialization phase.
Second, you don't nee to put try-catch blocks, you can just declare the Exception in your testMethod.
And it's better to use when() instead of stub(), like this:
#RunWith(MockitoJUnitRunner.class) public class MyTest {
#Mock
private MyHelper mockedDependency;
#InjectMocks
private MyService serviceUnderTest;
#Test
public void test1() throws Exception {
SomeObject someObject = null;
// create my stub
when(mockedDependency.doSomething("123", false, false)).thenReturn(someObject);
// run the implementation
ServiceResult serviceResult = serviceUnderTest.anotherMethod("123", false, false);
// check the state
assertNotNull(serviceResult);
// check the behaviour of the mock
verify(mockedDependency).doSomething("123", false, false);
}}
In your case line when(mockedDependency.doSomething is not important - test is checking the desired behaviour of MyServiceImpl anyway.

Related

Mockito spy not mocking internal call to mocked method

I have a class that calls out to a third party system to get data that I want to mock using Mockito. Here is some pseudo-code of how my class is setup.
// class I will be spying
public class SomeService {
// method I want to full test
public List<String> methodA(List<String> list) {
... omitted code ...
// internal call to method in the same class that will be mocked
innerList = methodB(list);
... omitted code ...
}
// method that I want to mock/spy
public List<String> methodB(List<String> list) {
//details omitted since it should be mocked any never called
}
}
Here is my test code. I setup my spy in a BeforeEach method to make sure that Mock is configured. When I directly call the mocked method, everything works as expected. When I call
public class SomeServiceTest{
private SomeService service;
#BeforeEach
public void init() {
service = Mockito.spy(SomeService.class);
// also tried with creating a new object but has same failure conditions
//service = Mockito.spy(new SomeService());
// mocking methodB with answer details omitted to reduce clutter
Mockito.doAnswer(..detail omitted..).when(service).methodB(Mockito.anyList());
}
//testing directly calling mocked method that returns mocked data
#Test
public void testMockedMethod() throws Exception {
List<String> list = //setup details ignored
List<String> results = service.methodB(list);
// follow up asserts work
}
//testing indirectly calling mocked method that call actual method code
#Test
public void testMethodA() throws Exception {
List<String> list = //setup details ignored
// NullPointer in methodB since mocking is ignore
List<String> results = service.methodA(list);
// assertions never tested since NPE was thrown
}
}
Does anyone know why when I directly call the mocked method, it returns the doAnswer; but when I indirectly call from within the mocked/spied object it ignores the fact that the method is mocked and calls the original method?
It should work. It seems to me that the NPE exception is because there are some bugs in your codes which already happen before it really executes the stubbed method . What is the stacktrack that you get ?
On the other hand, you can also add some println just before and after calling the stubbed method to verify the codes is really can execute up to that point :
public List<String> methodA(List<String> list) {
.......
System.out.println("before methodB");
innerList = methodB(list);
System.out.println("after methodB which return " + innerList);
....
}

Using PowerMockito how do I verify a constructor was called, with a specific set of arguments

Note: In anticipation of those that would like to point out the bad design of having code which constructs objects inside it, rather than via dependency injection, or factories, which are easily mocked; I am dealing with writing tests for legacy code, where refactoring the code into a more modern design is not an option.
I have a command method that when it executes will construct three objects in the class MyObjectWrapper, which is dependent on another class MyObject. In the test, both of these classes and the 6 objects are all mocked. Consider the following code:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyCommand.class)
public class MyCommandTest {
#Mock public MyObject objectOne;
#Mock public MyObject objectTwo;
#Mock public MyObject objectThree;
#Mock public MyObjectWrapper wrapperOne;
#Mock public MyObjectWrapper wrapperTwo;
#Mock public MyObjectWrapper wrapperThree;
private MyCommand command;
#Before public void beforeEach() {
command = new MyCommand();
MockitoAnnotations.initMocks(this);
initialiseWrapper(wrapperOne, objectOne, true, false);
initialiseWrapper(wrapperTwo, objectTwo, false, false);
initialiseWrapper(wrapperThree, objectThree, true, true);
}
private void initialiseWrapper(MyObjectWrapper wrapperMock, MyObject objMock, boolean option1, boolean option2) {
wrapperMock = PowerMockito.mock(MyObjectWrapper.class);
PowerMockito.whenNew(MyObjectWrapper.class)
.withParameters(MyObject.class, Boolean.class, Boolean.class)
.withArguments(objMock, option1, option2)
.thenReturn(wrapperMock);
}
#Test public void testConstructoresCalled() throws Exception {
command.execute();
VERIFY constructor with arguments: objectOne, true, false
VERIFY constructor with arguments: objectTwo, false, false
VERIFY constructor with arguments: objectThree, true, true
}
}
I know that I could confirm that the constructor was called 3 times with:
PowerMockito.verifyNew(MyObjectWrapper.class, times(3));
However I need to confirm that the constructors were called, with the three passed in arguments. Is it possible to do this?
PowerMockito.html#verifyNew returns a ConstructorArgumentsVerification, so use the returned object, see ConstructorArgumentsVerification javadoc

How can I have JMockit not mock a certain method?

I have a class that contains the following method, which I do not expect to ever return null:
public String getAutoSaveDir() {
if (autoSaveDir == null || autoSaveDir.isEmpty()) {
return System.getProperty("java.io.tmpdir");
} else {
return autoSaveDir;
}
}
I need to mock this class with #Injectable for other reasons.* Unfortunately, this means that this method returns null:
#Tested
private MyClass myClass;
#Injectable
private ClassContainingMethod classContainingMethod;
#Test
public void myTest() {
// Calls classContainingMethod.getAutoSaveDir()
myClass.saveFile();
}
This unfortunately fails, as getAutoSaveDir() returns null. I confirmed that System.getProperty("java.io.tmpdir") does not return null, so it seems that JMockit is mocking the method to return null, when I don't want it to.
I am aware that I can set up an Expectations block to tell it to just return System.getProperty("java.io.tmpdir"), but it seems really silly to mock it to return something that it would be returning anyway if unmocked.
How can I have JMockit not mock this method?
I am using JMockit 1.22 (would love to use a later version, but we have several instances of mocking private methods, which isn't allowed in later versions).
* I have to use #Injectable because the field is annotated with #Autowired. If I try to use a real instance, I get this error: java.lang.IllegalStateException: Missing #Injectable for field MyClass#classContainingMethod, of type com.example.ClassContainingMethod

Unable to execute test method from mocked class

I am writing unit test for methods to find banks near my location.
I mocked the class and tried to call the methods.
But, control is not going to method to execute it.
Below is unit test case.
#Test
public void testFindBanksByGeo() {
String spatialLocation = "45.36134,14.84400";
String Address = "Test Address";
String spatialLocation2 = "18.04706,38.78501";
// 'SearchClass' is class where 'target' method resides
SearchClass searchClass = Mockito.mock(SearchClass.class);
BankEntity bank = Mockito.mock(BankEntity.class);
// 'findAddressFromGeoLocation' and 'getGeo_location' to be mocked. They are called within 'target' method
when(searchClass.findAddressFromGeoLocation(anyString())).thenReturn(Address);
when(bank.getGeo_location()).thenReturn(spatialLocation2);
// 'writeResultInJson' is void method. so needed to 'spy' 'SearchClass'
SearchClass spy = Mockito.spy(SearchClass.class);
Mockito.doNothing().when(spy).writeResultInJson(anyObject(), anyString());
//This is test target method called. **Issue is control is not going into this method**
SearchedBanksEntity searchBanksEntity = searchClass.findNearbyBanksByGeoLocation(spatialLocation, 500);
assertNull(searchBankEntity);
}
What i have tried is also calling the real method on it,
Mockito.when(searchClass.findNearbyBanksByGeoLocation(anyString(), anyDouble())).thenCallRealMethod();
This calls real method but the methods i mocked above, are executing like real one. Means 'mocked methods' are not returning what i asked them to return.
So, what wrong i am doing here ?
why method is not executing?
The method is not getting called because you are calling it on a mock. You should call the method on an actual object.
Or you could use something like this before invoking the method.
Mockito.when(searchClass.findNearbyBanksByGeoLocation(Mockito.eq(spatialLocation), Mockito.eq(500))).thenCallRealMethod();
But I think this is not the way you should write the test. You shouldn't be mocking SearchClass in the first place. Instead there would be a dependency in SearchClass which gets you the address and geo location. You should be mocking that particular dependency.
OK, let's say we have this code:
class Foo {
// has a setter
SomeThing someThing;
int bar(int a) {
return someThing.compute(a + 3);
}
}
We want to test Foo#bar(), but there's a dependency to SomeThing, we can then use a mock:
#RunWith(MockitoJunitRunner.class)
class FooTest {
#Mock // Same as "someThing = Mockito.mock(SomeThing.class)"
private SomeThing someThing,
private final Foo foo;
#Before
public void setup() throws Exception {
foo = new Foo(); // our instance of Foo we will be testing
foo.setSomeThing(someThing); // we "inject" our mocked SomeThing
}
#Test
public void testFoo() throws Exception {
when(someThing.compute(anyInt()).thenReturn(2); // we define some behavior
assertEquals(2, foo.bar(5)); // test assertion
verify(someThing).compute(7); // verify behavior.
}
}
Using a mock we are able to avoid using a real SomeThing.
Some reading:
http://www.vogella.com/tutorials/Mockito/article.html
https://github.com/mockito/mockito/wiki

Calling method on real object instead calling on Mock object

I faced next issue when I have been writing Junit tests with using Mockito. My test invokes methods on real object instead mock object and I receive NullPointerException. Here is my code:
public class JSFUtilsTest {
public JSFUtilsTest() { }
JSFUtils jsfUtils = mock(JSFUtils.class);
FacesContext facesContext = ContextMocker.mockFacesContext();
ExternalContext extContext = mock(ExternalContext.class);
Application app = mock(Application.class);
ExpressionFactory exFactory = mock(ExpressionFactory.class);
ELContext elContext = mock(ELContext.class);
ValueExpression valExp = mock(ValueExpression.class);
#Test
public void testResolveExpression() {
when(jsfUtils.resolveExpression("expression")).thenAnswer(new Answer<Object>(){
public Object answer(InvocationOnMock invocation){
when(facesContext.getApplication()).thenReturn(app);
when(app.getExpressionFactory()).thenReturn(exFactory);
when(facesContext.getELContext()).thenReturn(elContext);
when(exFactory.createValueExpression(elContext, "expression", Object.class)).thenReturn(valExp);
when(valExp.getValue(elContext)).thenReturn(anyObject());
return valExp.getValue(elContext);
}
});
jsfUtils.resolveExpression(anyString());
verify(jsfUtils).resolveExpression(anyString());
assertNotNull(jsfUtils.resolveExpression(anyString()));
}
}
Instead calling resolveExpression() on Mock, I have got calling on JSFUtils object. JSFUtils.java and JSFUtilsTest.java are located in different packages. Can anybody help me? Thanks in advance!
I assume that this is just an example and in real test you do not call methods on the mock directly, but inject the dependencies to OUT.
You are expecting your mock to answer when you are calling jsfUtils.resolveExpression("expression"). In fact you are not calling it. I would suggest to change it to jsfUtils.resolveExpression(anyString()) and if you need it to be called with some specific string, you can check it the verify block: verify(jsfUtils).resolveExpression("expression");
Also calling jsfUtils.resolveExpression(anyString()); is not the right approach. Method anyString() is designed for stubbing not for real call.
Instead calling resolveExpression() on Mock, I have got calling on JSFUtils object.
Then do not create a mock, but a spy:
//JSFUtils jsfUtils = mock(JSFUtils.class);
JSFUtils jsfUtils = spy(new JSFUtils(/* mocks of dependencies if needed */));
But this is only needed if want to mock the return value of some other method in your class under test to force isolation of your unit.
This is not the case in your example as far as I see. So just write:
//JSFUtils jsfUtils = mock(JSFUtils.class);
JSFUtils jsfUtils = new JSFUtils(/* mocks of dependencies if needed */);
#Test
public void testResolveExpression() {
when(jsfUtils.resolveExpression("expression")).thenAnswer(new Answer<Object>(){
public Object answer(InvocationOnMock invocation){
when(facesContext.getApplication()).thenReturn(app);
when(app.getExpressionFactory()).thenReturn(exFactory);
when(facesContext.getELContext()).thenReturn(elContext);
when(exFactory.createValueExpression(elContext, "expression", Object.class)).thenReturn(valExp);
when(valExp.getValue(elContext)).thenReturn(anyObject());
return valExp.getValue(elContext);
}
});
jsfUtils.resolveExpression(anyString());
verify(jsfUtils).resolveExpression(anyString());
assertNotNull(jsfUtils.resolveExpression(anyString()));
This does not make any sense:
You mock the method of your class under test (cut) and then call that very same method. This way you do not verify the behavior of your cut but the behavior of the mocking framework.
Also you call the method twice within the same test method. You should avoid that.
You should change your test to this:
#Test
public void testResolveExpression() {
// arrange (test case specific setup of mocks and DTOs)
when(facesContext.getApplication()).thenReturn(app);
when(app.getExpressionFactory()).thenReturn(exFactory);
when(facesContext.getELContext()).thenReturn(elContext);
when(exFactory.createValueExpression(elContext, "expression", Object.class)).thenReturn(valExp);
when(valExp.getValue(elContext)).thenReturn(anyObject());
// act (call real method on real object)
Object result = jsfUtils.resolveExpression("a valid input");
// assert
assertNotNull(result );
}

Categories

Resources