问题
I have a method (method1) that I'd like to test, which based on parameters provided creates an object and calls another method (method2). So I'm mocking method2, which accepts an object (sampleObj).
public void method1(booleanParam) {
if(booleanParam){
List<SampleObj> fooList = new ArrayList<SampleObj>;
fooList.add(new SampleObj("another param"));
anotherService.method2(fooList);
}
//some other smart logic here
}
And here's my test with same obfuscated names (sorry if I missed any typo):
public void testMethod1() {
AnotherService mockedAnotherService = PowerMockito.mock(AnotherService.class);
ServicesFactory.getInstance().setMock(AnotherService.class, mockedAnotherService);
List<SampleObj> fooList = new ArrayList<SampleObj>;
fooList.add(new SampleObj("another param"));
// assert and verify
service.method1(true);
Mockito.verify(mockedAnotherService, times(1)).method2(fooList);
}
The problem is, when I try to mock the anotherService, I need to pass an object to method2, so I have to create a new one. But since it's a new object, it's not the same object, which will be passed from inside the method1, hence the test fails with the exception:
Argument(s) are different! Wanted:
anotherService.method2(
[com.smart.company.SampleObj@19c59e46]
);
-> at <test filename and line # here>
Actual invocation has different arguments:
anotherService.method2(
[com.smart.company.SampleObj@7d1a12e1]
);
-> at <service filename and line # here>
Any ideas how to accomplish that?
回答1:
You have a few options:
Implement
equals
andhashCode
onSampleObj
. Because you didn't wrapfooList
in a matcher, Mockito checks withList.equals
, which checksequals
for corresponding objects in each List. The default behavior of Object.equals is thata.equals(b)
iffa == b
--that is, objects are equal iff they refer to the same instance--but you're welcome to override that if every SampleObj("foobar") equals every other SampleObj("foobar").Use a Hamcrest Matcher you write.
private static Matcher<List<SampleObj>> isAListWithObjs(String... strings) { return new AbstractMatcher<List<SampleObj>>() { @Override public boolean matches(Object object) { // return true if object is a list of SampleObj corresponding to strings } }; } // in your test verify(mockedAnotherService).method2(argThat(isAnObjListWith("another param")));
Note that you could also just make a Matcher of a single SampleObj, and then use a Hamcrest wrapper like
hasItem
. See more matchers here.Use a Captor to check
equals
your own way:public class YourTest { // Populated with MockitoAnnotations.initMocks(this). // You can also use ArgumentCaptor.forClass(...), but with generics trouble. @Captor ArgumentCaptor<List<SampleObj>> sampleObjListCaptor; @Test public void testMethod1() { // ... verify(mockedAnotherService).method2(sampleObjListCaptor.capture()); List<SampleObj> sampleObjList = sampleObjListCaptor.getValue(); assertEquals(1, sampleObjList.size()); assertEquals("another param", sampleObjList.get(0).getTitle()); }
来源:https://stackoverflow.com/questions/30792006/mockito-how-to-mock-verify-a-method-call-which-accepts-a-new-object