33

I am using mockito as mocking framework. I have a scenerio here, my when(abc.method()).thenReturn(value) does not return value, instead it returns null.

public class DQExecWorkflowServiceImplTest {
@InjectMocks
DQExecWorkflowServiceImpl dqExecWorkflowServiceImpl = new DQExecWorkflowServiceImpl();
@Mock
private DQUtility dqUtility;
@Mock
private DqExec dqExec;
@Mock
private DqCntlDefn dqCntlDefn;
@Mock
private DqCntlWfDefn dqCntlWfDefn;
@Mock
private DqCntlWfDefnTyp dqCntlWfDefnTyp;
@Mock
private IDQControlWfDefTypeService controlWfDefTypeService;

@Before
public void setUp() throws Exception {
    dqExec = new DqExec();
    dqCntlWfDefn = new DqCntlWfDefn();
    dqUtility = new DQUtility();
    dqCntlWfDefnTyp = new DqCntlWfDefnTyp();
    dqCntlWfDefnTyp.setDqCntlWfDefnTypCd("MIN_INCLUSIVE_VAL");
    dqExecWorkflowServiceImpl
            .setControlWfDefTypeService(controlWfDefTypeService);

}

@Test
public void testExecuteWorkflow() {
    when(controlWfDefTypeService.getDqCntlWfDefnTypCd(dqCntlWfDefn))
            .thenReturn(dqCntlWfDefnTyp);
    dqExecWorkflowServiceImpl.executeWorkflow(dqExec, dqCntlWfDefn);
}

}

Java class

@Override
public DqCntlWfExec executeWorkflow(final DqExec dqExec,
        final DqCntlWfDefn dqCntlWfDefn) {
final DqCntlWfExec dqCntlWfExec = new DqCntlWfExec();
dqCntlWfExec.setDqCntlWfExecEffDt(dqUtil.getDefaultEffectiveDt());
dqCntlWfExec.setDqCntlWfExecExpDt(dqUtil.getDefaultExpiryDt());
dqCntlWfExec.setDqCntlWfDefn(dqCntlWfDefn);
dqCntlWfExec.setDqExec(dqExec);

final DqCntlWfDefnTyp dqCntlWfDefnTyp = controlWfDefTypeService
    .getDqCntlWfDefnTypCd(dqCntlWfDefn);
     String workflowType = null;
if(null!=dqCntlWfDefnTyp){
    workflowType = dqCntlWfDefnTyp.getDqCntlWfDefnTypCd();
}

When ever i run the test file the when is not working and i am using mockito1.8.5 jar in the buildpath. The service call is being mocked but returns the null value.

final DqCntlWfDefnTyp dqCntlWfDefnTyp = controlWfDefTypeService
    .getDqCntlWfDefnTypCd(dqCntlWfDefn);

This object dqCntlWfDefnTyp is null

I have done this before and there was no problem with the when, It seems to be working with files i have done before. I had followed the same procedure for the test file but i couldnt figure out the issue. Can anyone please assist me

Thanks to all the folks in advance

Gopi
  • 909
  • 1
  • 8
  • 15
  • 56
    Try reducing this to a smaller example, it's pretty unreadable. And I sure hope those names aren't under your control, because there is simply no excuse for `setDqCntlWfExecEffDt`. Note especially how inconsistent the code is in whether to use an abbreviation or not: `setDqCntlWfExecEffDt` vs `getDefaultEffectiveDt`, `executeWorkflow` vs `DqCntlWfExec`, etc. Seriously, the code could be submitted to TheDailyWTF as is. – Sebastian Redl Dec 11 '13 at 11:27
  • The code has been refactored and made it readable – Gopi Dec 11 '13 at 12:41
  • Can you add the error/output? How do you know it's `null`? Are you inferring it from `workflowType`... could it be that `.getDqCntlWfDefnTypCd()` is returning `null`? Etc... FWIW, I think the original code may hold the key to this. :-) – Jonathan Dec 11 '13 at 13:07
  • I am adding the whole set, since i could miss some information. – Gopi Dec 11 '13 at 13:48
  • 18
    Why would somebody use such naming UN-convention. Some people just want to watch the world burn.. – Mukul Goel Sep 23 '14 at 13:46

7 Answers7

48

Mockito mock works when we mock the objects loosely.

Here is the change i have made to make it work:

when(controlWfDefTypeService.getDqCntlWfDefnTypCd(any(DqCntlWfDefn.class))
    .thenReturn(dqCntlWfDefnTyp);

Instead of passing the object of the Mock class, I passed the class with the Matcher any() and it works.

Jonathan
  • 20,053
  • 6
  • 63
  • 70
Gopi
  • 909
  • 1
  • 8
  • 15
33

TL;DR If some arguments in your test are null, be sure to mock the parameter call with isNull() instead of any(SomeClass.class).


Explanation

This might not be the answer that helps OP, but might be useful for someone else. In my case the setup was all good, however, some mocks returned the desired thenReturn(...) value and some didn't.

It's important to understand, that the method call you're trying to mock (i.e. the method in when(someMock.methodToMock)) has to match the actual call and not the signature only.

In my case, I mocked a method with a signature:

public void SomeValue method(String string, SomeParam param)

The call however, in the test was something like:

method("some string during test", null);

Now if you mock the call with:

when(MockedClass.method(anyString(), any(SomeParam.class))

Mockito will not match it even though the signature is correct. The problem is that Mockito is looking for a call of method() with the arguments String and SomeParam, whereas the actual call was with a String and null. What you have to do is:

when(MockedClass.method(anyString(), isNull())

Hint

Since there are many isNull() implementations in different frameworks, be sure to use this one org.mockito.ArgumentMatchers.isNull.

Younes El Ouarti
  • 2,200
  • 2
  • 20
  • 31
10

I had the same problem. The solution for me was to put the Mockito.when(...).thenReturn(...); into the @Before-SetUp method.

Lazar Zoltan
  • 135
  • 3
  • 14
8

I think I have found your issue, but not all the credit goes to me.

Since you are trying to mock 'dqCntlWfDefnTyp' in your test class and the object itself is being instantiated in the class that you are trying to test, you inevitably run into some issues. The primary problem is that the object cannot be mocked because it is being recreated in during the test.

There are a few options, but the best choice in my humble opinion is using PowerMockito. You will be able to replace the object within the class that is being tested with the one you mock.

An excellent example of this usage of PowerMockito from @raspacorp on this question:

public class MyClass {
void method1{
    MyObject obj1=new MyObject();
    obj1.method1();
}
}

And the test class...

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MyClassTest {
@Test
public void testMethod1() {      
    MyObject myObjectMock = mock(MyObject.class);
    when(myObjectMock.method1()).thenReturn(<whatever you want to return>);   
    PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(myObjectMock);

    MyClass objectTested = new MyClass();
    objectTested.method1();

    ... // your assertions or verification here 
}
}
Community
  • 1
  • 1
Chad Van De Hey
  • 2,716
  • 3
  • 29
  • 46
  • when I do `objectTested = new MyClass();` spring still uses it's own created instance and does not honor the one configured in Test. Is there any way to work around this ? – Saurabh Bhoomkar May 14 '21 at 00:04
3

Just like Younes EO said: it usually is related to null arguments being passed to mocked functions.

One thing worth adding is that if you're using Kotlin for your tests (and you have mockito-kotlin in your project), for Nullable arguments you should usually use anyOrNull() instead of any().

Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
0

Relevant to the topic, just in case this helps someone. My mockito.when wasn't working when asserting anyString() reason being the String within the tested class was an injected value from a properties file. The following line set the injected value in the unit test:

ReflectionTestUtils.setField(bean, "theVariable", "theValue");
jawn
  • 851
  • 7
  • 10
0

I haved the same problem when i make test for controler. Use @MockBean instead @Mock

  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 28 '22 at 16:20