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

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

问题描述

我有一个要测试的方法(方法1),该方法根据提供的参数创建对象并调用另一个方法(方法2).所以我在嘲笑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进行检查,而List.equals会检查equals中每个列表中的对应对象. 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天全站免登陆