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

时间:2010-11-22 13:54:30

标签: java unit-testing mocking mockito partial-mocks

我遇到了Mockito的问题。

是否可以做这样的事情:

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") );
}  

正如他们所说,我避免使用当时的返回语法,这可能是间谍的一个问题(但无论如何它都不起作用)

奇怪的是: assertTrue(x.methodB(argument).equals(“good”)); 没问题

只有第二个 assertTrue(x.methodA(argument).equals(“good”)); 不行

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

在这种情况下,不可能告诉mockito返回“good”???看来当测试类调用methodB时没关系,但是如果spy的方法调用了methodB它就不再起作用了......

我不知道该做什么...对同一个类的2个方法进行单元测试并使测试彼此独立以使着名的模拟测试框架无法实现,这是多么奇怪的事情这个基本功能?这不是我们所说的真正的单元测试吗?不明白为什么他们说要避免在测试对象上使用间谍方法...

由于

2 个答案:

答案 0 :(得分:4)

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

ORIGINAL: 我真的很喜欢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);
    }

}

答案 1 :(得分:2)

间谍是与间谍物体不同的物体。间谍只委托间谍对象。因此,当间谍对象从methodA调用methodB时,它将自己调用它,而不是调用间谍。