java - Mockito when/then not returning expected value -


i'm trying stub getkeyfromstream method, using 'any' matchers. i've tried being more explicit , less explicit (anyobject()), seems no matter try, stub not return fookey in unit test.

i'm wondering if because protected or there else i'm missing or doing incorrectly. have other when/then statements throughout tests are working reason here, not.

note: getkeyfromstream uses bytearrayinputstream, i'm trying match inputstream, i've tried both no avail.

public class fookeyretriever() //mocked guy {     public fookey getkey(string keyname) throws keyexception {          return getkeyfromstream(getkeystream(keyname, false), keyname);     }      //stubbed method return key object has been mocked     protected fookey getkeyfromstream(inputstream keystream, string keyname){         //some code         return fookey;     } } 

unit test

@mock private fookeyretriever mockkeyretriever;  @mock private fookey fookey;  @before public void setup() throws exception {         mockitoannotations.initmocks(this); }  @test public void testgetfookey() throws exception {        when(foo.getkeyfromstream(any(inputstream.class),any(string.class))).thenreturn(fookey);      fookey fookey = mockkeyretriever.getkey("irrelevant_key");      assertnotnull(fookey); } 

the problem unit-test is, trying mock method of actual class want test can't invoke mock method return null unless declare mocked return value on invoked method. usually, mock external dependencies.

there 2 ways create test-objects: mock , spy. primer 1 create new object based on class provided has internal state null , return null on every invoked method. that's why need define return values method invocations. spy on other hand creates real object , intercepts method invocations if "mock definitions" defined methods.

mockito , powermock provide 2 ways of defining mocked methods:

// method 1 when(mockedobject.methodtomock(any(param1.class), any(param2.class),...)     .thenreturn(answer); when(mockedobject, method(dependency.class, "methodtomock", parameter1.class, parameter2.class, ...)     .thenreturn(answer); 

or

// method 2 doreturn(answer).when(mockedobject).methodtomock(param1, param2); 

the difference is, method 1 execute methods implementation while later 1 won't. important if deal spy objects don't want execute real code inside invoked method instead replace code or return predefined value!

although mockito , powermock provide docallrealmethod() can define instead of doreturn(...) or dothrow(...), invoke , execute code within real object , ignores mocked method return statements. though, not useful in case want mock method of class under test.

a method implementation can "overwritten"

doanswer(answer<t>() {      @override      public t answer(invocationonmock invocation) throws throwable {         ...     } ) 

where can declare logic of invoked method should be. can utilize return mock result of protected method therefore this:

import static org.hamcrest.core.issame.sameinstance; import static org.junit.assert.assertthat; import static org.mockito.mockito.mock; import static org.mockito.mockito.spy; import static org.mockito.mockito.doreturn; import static org.mockito.mockito.doanswer; import static org.mockito.matchers.any; import static org.mockito.matchers.anystring;  import java.io.inputstream;  import org.junit.test; import org.mockito.invocation.invocationonmock; import org.mockito.stubbing.answer;  public class fookeyretrievertest {      @test     public void testgetfookey() throws exception {         // arrange         final fookeyretriever sut = spy(new fookeyretriever());         fookey mockedkey = mock(fookey.class);          doreturn(mockedkey)             .when(sut).getkeyfromstream(any(inputstream.class), anystring());         doanswer(new answer<fookey>() {              public fookey answer(invocationonmock invocation) throws throwable {                 return sut.getkeyfromstream(null, "");             }         }).when(sut).getkey(anystring());          // act         fookey ret = sut.getkey("test");          // assert         assertthat(ret, sameinstance(mockedkey));     } } 

the code above works, note has same semantic declaring return value getkey(...) as

doreturn(mockedkey).when(sut).getkey(anystring()); 

trying modify getkeyfromstream(...) this:

doreturn(mockedkey)     .when(sut).getkeyfromstream(any(inputstream.class), anystring()); 

without modifying getkey(...) of system-under-test (sut) won't achieve real code of getkey(...) executed. if mock sut-object, not invoke method in // act section return null. if try

docallrealmethod().when(sut).getkey(anystring()); 

on mock object, real method woulb called , mentiond beforehand, invoke real implementations of getkeyfromstream(...) , getkeystream(...) regardless specified mock-method.

as can see yourself, mocking methods of actual class under test not useful , puts more burden provides good. therefore, it's or enterprise' policy if want or need test private/protected methods @ or if stick testing public api (which recommend). have possibility refactor code in order improve testability although primary intent of refactoring should improve overall design of code.


Comments