Mockito - 如何模拟/验证接受新对象的方法调用?

时间:2015-06-11 21:45:53

标签: unit-testing junit mockito powermock

我有一个我想测试的方法(method1),它基于提供的参数创建一个对象并调用另一个方法(method2)。所以我在模拟method2,它接受一个对象(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
}

这是我的测试用同样混淆的名字(抱歉,如果我错过任何错字):

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);
}

问题是,当我尝试模拟anotherService时,我需要将一个对象传递给method2,所以我必须创建一个新对象。但由于它是一个新对象,它不是同一个对象,它将从method1内部传递,因此测试失败,但有例外:

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>

任何想法如何实现?

1 个答案:

答案 0 :(得分:2)

您有几个选择:

  1. equals上实施hashCodeSampleObj。因为您没有在匹配器中包裹fooList,所以Mockito会检查List.equalsequals会检查a.equals(b)中每个列表中的相应对象。 Object.equals的默认行为是a == b iff 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"))); - 也就是说,如果对象引用相同的实例,则对象是相同的 - 但是如果每个SampleObj都欢迎您覆盖它(&#34; foobar&#34;)等于所有其他SampleObj(&#34; foobar&#34;)。

  2. 使用你写的Hamcrest Matcher。

    hasItem

    请注意,您也可以只创建一个SampleObj的Matcher,然后使用像equals这样的Hamcrest包装器。 See more matchers here.

  3. 使用Captor以您自己的方式检查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()); }

    /*
    
        GET users listing.
        */
    
    exports.list = function(req, res){
    res.send("respond with a resource");
    };