【问题标题】:Mockito when checking for specific object property value检查特定对象属性值时的 Mockito
【发布时间】:2017-03-03 19:40:04
【问题描述】:

我在工作测试中有以下内容:

when(client.callApi(anyString(), isA(Office.class))).thenReturn(responseOne);

请注意,client 是 Client 类的 Mock。

我想更改“isA(Office.class)”以告诉它匹配 Office 实例的“id”属性为“123L”的位置。如何在模拟对象的方法中指定我想要一个特定的参数值?

编辑:不是重复的,因为我试图在“何时”使用它,并且链接的问题(以及我发现的其他资源)在“验证”和“断言”上使用 ArgumentCaptor 和 ArgumentMatcher。我在想我实际上不能做我正在尝试的事情,我会尝试另一种方式。当然,我愿意以其他方式展示。

【问题讨论】:

标签: java mockito


【解决方案1】:

按要求重新打开,但解决方案(使用 ArgumentMatcher)与 the one in the linked answer 相同。当然,你不能在存根时使用ArgumentCaptor,但其他一切都是一样的。

class OfficeWithId implements ArgumentMatcher<Office> {
  long id;

  OfficeWithId(long id) {
    this.id = id;
  }

  @Override public boolean matches(Office office) {
    return office.id == id;
  }

  @Override public String toString() {
    return "[Office with id " + id + "]";
  }
}

when(client.callApi(anyString(), argThat(new IsOfficeWithId(123L)))
    .thenReturn(responseOne);

因为 ArgumentMatcher 只有一个方法,您甚至可以在 Java 8 中将其设为 lambda:

when(client.callApi(anyString(), argThat(office -> office.id == 123L))
    .thenReturn(responseOne);

如果您已经在使用 Hamcrest,您可以使用 MockitoHamcrest.argThat 适配 Hamcrest 匹配器,或使用内置的 hasPropertyWithValue

when(client.callApi(
         anyString(),
         MockitoHamcrest.argThat(hasPropertyWithValue("id", 123L))))
    .thenReturn(responseOne);

【讨论】:

  • 谢谢。项目中的某些内容似乎设置不正确并且不喜欢 argThat。我稍后会解决这个问题。
  • @eflat 检查您的版本。 argThat 在 1.x 和 2.x 之间变化;在 1.x Mockito 的 ArgumentMatcher 扩展 Hamcrest 的 MatcherMatchers.argThat 支持两者,但它们在 2.x 中为了更好的版本控制而产生分歧,Hamcrest argThat 变为 MockitoHamcrest.argThat。如果您的类路径中同时包含这两个版本,那么可能会发生疯狂的事情。
【解决方案2】:

我最终选择了“eq”。在这种情况下这没问题,因为对象非常简单。首先,我创建了一个与我期望返回的对象相同的对象。

Office officeExpected = new Office();
officeExpected.setId(22L);

然后我的'when'语句变为:

when(client.callApi(anyString(), eq(officeExpected))).thenReturn(responseOne);

这让我可以进行比“isA(Office.class)”更好的检查。

【讨论】:

    【解决方案3】:

    为任何拥有更复杂对象的人添加答案。

    OP 的回答使用eq,它适用于简单对象。

    但是,我有一个包含更多字段的更复杂的对象。创建 Mock 对象并填写所有字段非常痛苦

    public class CreateTenantRequest {
      @NotBlank private String id;
      @NotBlank private String a;
      @NotBlank private String b;
      ...
      ...
      
    }
    

    我能够使用refEq 来实现相同的目标,而无需设置每个字段的值。

    Office officeExpected = new Office();
    officeExpected.setId(22L);
    
    verify(demoMock, Mockito.atLeastOnce()).foobarMethod(refEq(officeExpected, "a", "b"));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-11
      • 2017-10-09
      • 2021-03-12
      • 2020-06-15
      • 1970-01-01
      相关资源
      最近更新 更多