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
Post a Comment