【问题标题】:Mockito - how to mock/verify a method call which accepts a new object?Mockito - 如何模拟/验证接受新对象的方法调用?
【发布时间】:2015-06-11 21:45:53
【问题描述】:

我有一个我想测试的方法 (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>

有什么想法可以实现吗?

【问题讨论】:

    标签: unit-testing junit mockito powermock


    【解决方案1】:

    你有几个选择:

    1. SampleObj 上实现equalshashCode。因为您没有将 fooList 包装在匹配器中,所以 Mockito 会检查 List.equals,后者会检查 equals 在每个列表中的对应对象。 Object.equals 的默认行为是 a.equals(b) iff a == b - 也就是说,如果对象引用相同的实例,则它们是相等的 - 但如果每个 SampleObj("foobar") 等于,欢迎您覆盖它每隔一个 SampleObj("foobar")。

    2. 使用您编写的 Hamcrest Matcher。

      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 的 Matcher,然后使用像 hasItem 这样的 Hamcrest 包装器。 See more matchers here.

    3. 使用 Captor 以您自己的方式检查 equals

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-01
      • 2018-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 1970-01-01
      • 2012-08-09
      相关资源
      最近更新 更多