Mockito - 如何模拟/验证接受新对象的方法调用? [英] Mockito - how to mock/verify a method call which accepts a new object?

查看:33
本文介绍了Mockito - 如何模拟/验证接受新对象的方法调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个我想测试的方法 (method1),它基于提供的参数创建一个对象并调用另一个方法 (method2).所以我在嘲笑method2,它接受一个对象(sampleObj).

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

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

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. SampleObj 上实现 equalshashCode.因为您没有将 fooList 包装在匹配器中,所以 Mockito 使用 List.equals 进行检查,后者检查 equals 以查找每个 List 中的相应对象.Object.equals 的默认行为是 a.equals(b) iff a == b——也就是说,当对象引用同一个实例时,它们是相等的——- 但如果每个 SampleObj("foobar") 都等于其他所有 SampleObj("foobar"),则欢迎您覆盖它.

  1. Implement equals and hashCode on SampleObj. Because you didn't wrap fooList in a matcher, Mockito checks with List.equals, which checks equals for corresponding objects in each List. The default behavior of Object.equals is that a.equals(b) iff a == 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").

使用您编写的 Hamcrest Matcher.

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

请注意,您也可以只制作单个 SampleObj 的 Matcher,然后使用像 hasItem 这样的 Hamcrest 包装器.在此处查看更多匹配器.

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.

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

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

这篇关于Mockito - 如何模拟/验证接受新对象的方法调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆