简体   繁体   English

如何验证使用 Mockito 调用了两种方法之一?

[英]How can I verify that one of two methods was called using Mockito?

Suppose I have a class with two methods where I don't care which is called...假设我有一个有两种方法的类,我不在乎哪个被调用......

public class Foo {
    public String getProperty(String key) {
        return getProperty(key, null);
    }
    public String getProperty(String key, String defaultValue) {
        //...
    }
}

Both the below (from another class, still in my application) should pass my test:以下两个(来自另一个类,仍在我的应用程序中)都应该通过我的测试:

public void thisShouldPass(String key) {
    // ...
    String theValue = foo.getProperty(key, "blah");
    // ...
}

public void thisShouldAlsoPass(String key) {
    // ...
    String theValue = foo.getProperty(key);
    if (theValue == null) {
        theValue = "blah";
    }
    // ...
}

I don't care which was called, I just want one of the two variants to be called.我不在乎调用了哪个,我只想调用两个变体之一。

In Mockito, I can generally do things like this:在 Mockito 中,我通常可以做这样的事情:

Mockito.verify(foo, atLeastOnce()).getProperty(anyString());

Or:或者:

Mockito.verify(foo, atLeastOnce()).getProperty(anyString(), anyString());

Is there a native way to say "verify either one or the other occurred at least once"?是否有一种本地方式可以说“验证一个或另一个至少发生一次”?

Or do I have to do something as crude as:或者我是否必须做一些粗略的事情:

try {
    Mockito.verify(foo, atLeastOnce()).getProperty(anyString());
} catch (AssertionError e) {
    Mockito.verify(foo, atLeastOnce()).getProperty(anyString(), anyString());
}

You could use atLeast(0) in combination with ArgumentCaptor :您可以将atLeast(0)ArgumentCaptor结合使用:

ArgumentCaptor<String> propertyKeyCaptor = ArgumentCaptor.forClass(String.class);
Mockito.verify(foo, atLeast(0)).getProperty(propertyKeyCaptor.capture(), anyString());

ArgumentCaptor<String> propertyKeyCaptor2 = ArgumentCaptor.forClass(String.class);
Mockito.verify(foo, atLeast(0)).getProperty(propertyKeyCaptor2.capture());

List<String> propertyKeyValues = propertyKeyCaptor.getAllValues();
List<String> propertyKeyValues2 = propertyKeyCaptor2.getAllValues();

assertTrue(!propertyKeyValues.isEmpty() || !propertyKeyValues2.isEmpty()); //JUnit assert -- modify for whatever testing framework you're using

Generally, if you're calling verify on a "getter" of any sort, you're assuming too much about the implementation.通常,如果您在任何类型的“getter”上调用verify ,那么您对实现的假设就太多了。 Mockito is generally designed for flexible tests (compared to "brittle" test that need to change even if the code is correct); Mockito 通常是为灵活的测试而设计的(相对于即使代码正确也需要更改的“脆弱”测试); your test should care more about whether the value is correct as opposed to which methods were used to get that value.您的测试应该更关心的值是否正确,而不是使用方法,获得价值。 A better solution might be to stub both getters to return a predictable value, and then use a normal assertion against the same value to ensure it plumbs through to the correct place.更好的解决方案可能是将两个 getter存根以返回一个可预测的值,然后对相同的值使用正常的断言以确保它直通到正确的位置。

when(mockFoo.getProperty("bar")).thenReturn("bar value");
when(mockFoo.getProperty("bar", anyString())).thenReturn("bar value");
// ...
assertEquals("bar value", new SystemUnderTest(mockFoo).getBarProperty());

Mockito's documentation spells this out: Mockito 的文档说明了这一点:

Although it is possible to verify a stubbed invocation, usually it's just redundant.尽管可以验证存根调用,但通常它只是多余的。 Let's say you've stubbed foo.bar() .假设您已存根foo.bar() If your code cares what foo.bar() returns then something else breaks (often before even verify() gets executed).如果您的代码关心foo.bar()返回什么,那么其他东西就会中断(通常甚至在verify()执行之前)。 If your code doesn't care what get(0) returns then it should not be stubbed.如果你的代码不关心get(0)返回什么,那么它不应该被存根。

That said, if this is a pattern you're required to support (or a method call with both overloads and side-effects) you can get a lot of information via Mockito.mockingDetails and MockingDetails.getInvocations , including invocations as of Mockito 1.10.0.也就是说,如果这是您需要支持的模式(或具有重载和副作用的方法调用),您可以通过Mockito.mockingDetailsMockingDetails.getInvocations获得大量信息,包括自 Mockito 1.10 起的调用。 0. You would need to loop through the Invocation objects to check against multiple methods.您需要遍历 Invocation 对象以检查多个方法。

boolean found = false;
Method method1 = Foo.class.getMethod("getProperty", String.class);
Method method2 = Foo.class.getMethod("getProperty", String.class, String.class);
for (Invocation invocation : Mockito.mockingDetails(foo).getInvocations()) {
  if (method1.equals(invocation.getMethod())
      || method2.equals(invocation.getMethod()) {
    found = true;
    break;
  }
}
assertTrue("getProperty was not invoked", found);

Note that this second solution is a little dangerous, as it does not benefit from automatic refactoring tools built into IDEs, and may be harder to read than some other solutions.请注意,第二个解决方案有点危险,因为它无法从 IDE 中内置的自动重构工具中受益,并且可能比其他一些解决方案更难阅读。 (The above may also be missing calls to isIgnoredForVerification , markVerified , and other niceties.) However, if you foresee needing this frequently across a large codebase, then using Mockito's built-in APIs may afford you much more flexibility than you would have otherwise. (以上可能还缺少对isIgnoredForVerificationmarkVerified和其他细节的调用。)但是,如果您预见在大型代码库中经常需要这样做,那么使用 Mockito 的内置 API 可能会为您提供比其他方式更大的灵活性。

In your particular case, getProperty(String) calls getProperty(String, String) internally.在您的特定情况下, getProperty(String) getProperty(String, String)内部调用getProperty(String, String)

public String getProperty(String key) {
    /*
     * getProperty(String, String) is called anyway.
     * Why not simply verify the occurrence of that?
     */
    return getProperty(key, null);
}

Simply verifying the second method would be equivalent to verifying the occurrence of either one or the other at least once.简单地验证第二种方法相当于至少验证一个或另一个的出现一次。

Mockito.verify(foo, atLeastOnce()).getProperty(anyString(), anyString());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Mockito来验证是否调用了一组重载方法中的任何一个/一个? - How can I use Mockito to verify that any/none of a set of overloaded methods is called? 我们可以使用 Mockito 验证在几个对象之一上调用了一个方法吗 - Can we verify a method is called on one of the several objects using Mockito 使用Mockito,如何验证方法是否具有某个参数? - Using Mockito, how do I verify a method was a called with a certain argument? 我可以使用Mockito存储通过反射调用的方法吗? - Can I stub methods called through reflection using Mockito? 如何验证未使用 Mockito 调用特定方法? - How to verify that a specific method was not called using Mockito? 当随后更改 state 时,如何验证使用特定 object state 调用 Mockito 模拟? - How can I verify a Mockito mock is called with a specific object state when that state is subsequently changed? 使用Mockito,如何验证我的lambda表达式被调用? - With Mockito, how do I verify my lambda expression was called? 如何使用 JUnit Mockito 验证未调用方法 - How to check that a method is not being called using JUnit Mockito Verify 如何使用Mockito验证未使用任何参数组合调用的模拟方法 - How to verify mocked method not called with any combination of parameters using Mockito 验证是否使用mockito调用了三种方法之一 - Verify whether one of three methods is invoked with mockito
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM