2010-08-24 116 views
108

我已经使用了这个,但没有找到任何相关的。我有这样的事情:Mockito。验证方法参数

Object obj = getObject(); 
Mockeable mock= Mockito.mock(Mockeable.class); 
Mockito.when(mock.mymethod(obj)).thenReturn(null); 

Testeable obj = new Testeable(); 
obj.setMockeable(mock); 
command.runtestmethod(); 

现在,我想验证mymethod(Object o),这就是所谓的内部runtestmethod(),被称为与对象o,没有任何其他的。但我始终通过测试,无论我穿上了验证,例如,具有:

Mockito.verify(mock.mymethod(Mockito.eq(obj))); 

Mockito.verify(mock.mymethod(Mockito.eq(null))); 

Mockito.verify(mock.mymethod(Mockito.eq("something_else"))); 

我总是通过测试。我如何完成验证(如果可能的话)?

谢谢。

回答

40
  • 如果您不使用其他匹配器,则不需要eq匹配器。
  • 您没有使用正确的语法 - 您的方法调用应该在.verify(mock)之外。您现在正在对方法调用的结果启动验证,而不验证任何内容(不进行方法调用)。因此所有测试都通过了。

你的代码应该是这样的:

Mockito.verify(mock).mymethod(obj); 
Mockito.verify(mock).mymethod(null); 
Mockito.verify(mock).mymethod("something_else"); 
+0

我曾尝试过,现在再次确定。我仍然有同样的问题,测试总是通过。 – manolowar 2010-08-24 10:41:34

+1

那么也许你没有足够的表现。这应该工作。 – Bozho 2010-08-24 10:54:03

3

你检查的mockable类equals方法?如果这个返回值总是为真,或者你对同一个实例测试了同一个实例,并且同等方法没有被覆盖(因此只针对引用进行检查),那么它返回true。

48

你是否试图利用对象的.equals方法来做逻辑平等?这种利用包含在在的Mockito匹配argThat

import static org.mockito.Matchers.argThat 

接下来,你可以实现自己的参数匹配

private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> { 
    T thisObject; 

    public ObjectEqualityArgumentMatcher(T thisObject) { 
     this.thisObject = thisObject; 
    } 

    @Override 
    public boolean matches(Object argument) { 
     return thisObject.equals(argument); 
    } 
} 

现在用你的代码,你可以将推迟到每个对象.equals方法你可以做更新阅读...

Object obj = getObject(); 
Mockeable mock= Mockito.mock(Mockeable.class); 
Mockito.when(mock.mymethod(obj)).thenReturn(null); 

Testeable obj = new Testeable(); 
obj.setMockeable(mock); 
command.runtestmethod(); 

verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj))); 

如果你只是去精确的相等(在内存中同一个对象),只是做

verify(mock).mymethod(obj); 

这将验证它被调用一次。

+1

您可以使用'ReflectionEquals'类中的构建来达到此目的。 – takacsot 2014-04-16 06:23:04

+2

+1为您的答案。但是我想补充一下'verify(mock).mymethod(obj);'不检查EXACT是否相等(内存中的同一个对象)。相反,它使用本来可能被overwridden的对象equals-method。 – efux 2015-05-20 18:32:29

+0

您也可以创建'ArgumentMatcher'的匿名实现,以减少冗长。 – botchniaque 2015-09-01 13:07:59

1

你用同一个()匹配器试过吗?如在:

verify(mockObj).someMethod(same(specificInstance)); 

我有同样的问题。我使用eq()匹配器以及refEq()匹配器尝试了它,但我总是有误报。当我使用相同的()匹配器时,当参数是不同的实例并且一旦参数是相同的实例时,测试失败。

140

ArgumentMatcher的替代方法是ArgumentCaptor

正式例如:

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class); 
verify(mock).doSomething(argument.capture()); 
assertEquals("John", argument.getValue().getName()); 

一个俘虏也可以使用@Captor注释中定义:

@Captor ArgumentCaptor<Person> captor; 
//... MockitoAnnotations.initMocks(this); 
@Test public void test() { 
    //... 
    verify(mock).doSomething(captor.capture()); 
    assertEquals("John", captor.getValue().getName()); 
} 
+0

谢谢你的样品!从未使用它。在代码中感觉像* captor *之类的东西有点奇怪,但它有帮助。 – Artemis 2016-03-01 14:32:24

+0

哈哈,我不明白这个问题,但答案帮了我很多。感谢:-) – 2017-11-14 12:54:35

+0

重要:使用模拟调用verify()/ capture()_after_。我以为它必须在......之前“安装”...... – 2018-02-21 16:02:58

-1

您还可以使用TypeSafeDiagnosingMatcher

private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) { 
    return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() { 

     StringBuilder text = new StringBuilder(500); 

     @Override 
     protected boolean matchesSafely(GetPackagesRequest req, Description desc) { 
      String productCode = req.getPackageIds().iterator().next().getValue(); 
      if (productCode.equals(request.getSupplierProductCode())) { 
       text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode()); 
       return true; 
      } 

      text.append(req.toString()); 
      return false; 
     } 

     @Override 
     public void describeTo(Description d) { 
      d.appendText(text.toString()); 
     } 
    }; 
} 

然后验证调用:

Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request))); 
2

另一种方法是使用org.mockito.internal.matchers.Equals.Equals方法,而不是重新定义之一:

verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted))); 
0

我已经以这种方式

@UnitTest 
public class JUnitServiceTest 
{ 
    @Mock 
    private MyCustomService myCustomService; 


    @Test 
    public void testVerifyMethod() 
    { 
     Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0)) 
     Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times 
     Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time 
     Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times 
     Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times 
     Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); // no other method called except this 
    } 
} 
使用Mockito.verify