Java 使用mockito进行单元测试(部分模拟)

Java 使用mockito进行单元测试(部分模拟),java,unit-testing,mocking,mockito,partial-mocks,Java,Unit Testing,Mocking,Mockito,Partial Mocks,我对莫基托有意见 有没有可能做这样一件事: ClassX x = mock(ClassX.class) when(x.methodB()).thenReturn("toto"); String result = x.methodA(); 我在用Mockito 1.7 我看到有一个“间谍”系统,但他们说不建议在我们测试的项目上使用它(为什么?) 不管怎样,我试过那个间谍功能,但我有一种奇怪的行为 检查我想做什么: 实数代码: String methodA(String arg) { re

我对莫基托有意见

有没有可能做这样一件事:

ClassX x = mock(ClassX.class)
when(x.methodB()).thenReturn("toto");
String result = x.methodA();
我在用Mockito 1.7

我看到有一个“间谍”系统,但他们说不建议在我们测试的项目上使用它(为什么?)

不管怎样,我试过那个间谍功能,但我有一种奇怪的行为

检查我想做什么:

实数代码:

String methodA(String arg) {
    return this.methodB(arg);
}

String methodB(String arg) {
    return "toto";
}
测试代码:

@Test
public void testTest() {
    final ClassX x = spy( new ClassX() );
    final String argument = "arg";
    doReturn("good").when(helper).methodB(argument);
    assertTrue(  x.methodB(argument).equals("good") );
    assertTrue(  x.methodA(argument).equals("good") );
}  
正如他们所说,我避免了when-thenReturn语法,这可能是间谍的问题(但无论如何它也不起作用)

奇怪的是: assertTrue(x.methodB(参数).equals(“good”); 没关系

只有第二个 assertTrue(x.methodA(参数).equals(“good”); 不好

实际上,helper.methodA(参数)返回“toto”->实际结果,而不是模拟结果

在这种情况下,不可能让mockito返回“good”???当测试类调用methodB时,它似乎没有问题,但是如果间谍的方法调用methodB,它就不再工作了

我不知道该怎么办。。。对同一类的两个方法进行单元测试并使测试相互独立,以至于一个著名的模拟测试框架无法实现这个基本功能,这是不是很奇怪?这不是我们所说的真正的单元测试吗?我不明白为什么他们说要避免在测试对象上使用间谍方法


谢谢

间谍与被间谍不同。间谍只委派给被间谍的对象。因此,当spied对象从methodA调用methodB时,它将在自身而不是spy上调用它。

更新: 我写了下面的内容,不久之后发现了.thenCallRealMethod(),它允许您有效地执行部分存根。Mockito的作者建议您使用重构将依赖项分离到不同的类中;但它们确实提供了部分存根的方法。我添加了一个测试方法来演示这种方法,并留下了我的原始评论

原件: 我真的很喜欢Mockito,但这是EasyMock获胜的地方。我有两个不涉及Mockito的解决方案。第一个是覆盖测试实例上的methodB。另一个是使用EasyMock进行部分模拟:

import org.junit.Test;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;

public class PartialMockTest {

    class ClassX {
        String methodA(String arg) {return methodB(arg);}
        String methodB(String arg) {return "toto";}
    }

    @Test
    public void MockitoOnClassX(){
        ClassX classx = mock(ClassX.class);
        when(classx.methodB("hiyas")).thenReturn("tomtom");
        when(classx.methodA(anyString())).thenCallRealMethod();
        String response = classx.methodA("hiyas");
        assertEquals("tomtom",response);
    }


    @Test
    public void OverrideOnClassX() {
        ClassX classx = new ClassX(){@Override String methodB(String arg){return "tomtom";}};
        String response = classx.methodA("hiyas");
        assertEquals("tomtom",response);
    }

    @Test
    public void PartialMockOnClassX() throws NoSuchMethodException {
        ClassX classx = createMockBuilder(ClassX.class).addMockedMethod("methodB").createMock();
        expect(classx.methodA("hiyas")).andReturn("tomtom");
        replay(classx);
        String response = classx.methodA("hiyas");
        assertEquals("tomtom",response);
    }

}

谢谢:)但是你有一个解决方案来做我想做的吗?我想我可以使用一个匿名的实类并重写MethodB,但是mockito没有给出一个合适的解决方案?而是将
MethodB
放在另一个对象上,这个对象作为具有
methodA
的对象的依赖项,例如作为构造函数参数。这样就可以模拟
methodB
对象。如果你给出你的对象和方法的专有名称,我可以为你推荐更好的名称。谢谢。因此,似乎没有办法使用spy并将这两个方法放在同一个类中。。。SAD应该仅仅为了模拟和测试而将
methodB
移出,即使(1)methodA和
methodB
完全属于同一类,并且(2)
methodB
methodA
使用的一段常见代码?只需在Mockito 1.9.5中尝试了这一点,并且都返回了
“good”
。所以我想这种行为已经消失了。