java - Mockito 的 doReturn() 方法未在代码中返回所需的值

标签 java unit-testing junit mockito junit4

我正在尝试对以下方法进行单元测试:

Class TestClass {

    public List<String> test(String a, String b, String c, String d) throws IOException {
      MyClass myClass = new MyClass();
      myClass.setFileName(functionName);
      int outputNum = myClass.getOutputTableArgsSize();
      List<String> list = new ArrayList<String> ();



      ... and some more code based on outputNum value.

      return list;
    }
}

我的单元测试方法如下所示:

    @Test
    public void testMyTestClass() throws Exception {
        TestClass myClass = new TestClass();
        MyClass myClass = mock(MyClass.class);
        doNothing().when(myClass).setFileName(anyString());
        doReturn(11).when(myClass).getOutputTableArgsSize();

        .... Some more lines and based on return value 11, I am expecting the size of the list to be return is 1. 

        assertEquals(TestClass.test("ab", "cd", "ef", "gh").size(), 1);
    }

我试图在第 1 行返回 11 doReturn(11).when(myClass).getOutputTableArgsSize(); 但是当我检查返回值时总是 0。

上面的单元测试有什么问题,为什么我总是得到 0 insted of doReturn() 中提到的值?

最佳答案

测试中的模拟

 MyClass myClass = mock(MyClass.class);

不是被测方法中使用的实例,因为被测方法创建了自己的实例。

public List<String> test(String a, String b, String c, String d) throws IOException {
    MyClass myClass = new MyClass();
    //...

被测方法与实现问题紧密耦合,这使得单独测试它变得困难。

考虑重构被测主题类,以通过构造函数注入(inject)显式依赖该类。

如果每次调用都需要一个新实例,那么请考虑使用工厂

public interface MyClassFactory {
    public MyClass Create(string functionName);
}

public class MyClassFactoryImp implements MyClassFactory {
    public MyClass Create(string functionName) {
        MyClass myClass = new MyClass();
        myClass.setFileName(functionName);
        return myClass
    }
}

并相应地重构主题类

class TestClass {
    MyClassFactory factory;
    public TestClass(MyClassFactory factory) {
        this.factory = factory;
    }

    public List<String> test(String a, String b, String c, String d) throws IOException {
      MyClass myClass = factory.Create(functionName);
      int outputNum = myClass.getOutputTableArgsSize();
      List<String> list = new ArrayList<String> ();

      //... and some more code based on outputNum value.

      return list;
    }
}

这样就可以构造和执行适当的隔离测试

@Test
public void testMyTestClass() throws Exception {
    //Arrange
    MyClass myClass = mock(MyClass.class);
    doNothing().when(myClass).setFileName(anyString());
    doReturn(11).when(myClass).getOutputTableArgsSize();

    MyClassFactory factory = mock(MyClassFactory.class);
    doReturn(myClass).when(factory).Create(anyString());

    TestClass subject = new TestClass(factory);

    //Act
    List<String> result = subject.test("ab", "cd", "ef", "gh");

    //Assert
    assertEquals(result.size(), 1);
}

关于java - Mockito 的 doReturn() 方法未在代码中返回所需的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57702419/

相关文章:

java - Log4j 挂起我的应用程序

ios - 单元测试单例 : mock and swizzle

java - 如何模拟一个完整的方法?

java - 获取JUNIT中@Before中当前执行的@Test方法名

junit - 在 Junit 测试脚本中注入(inject) CDI bean

java - Java GUI 的问题

java - Android自定义ViewGroup绘制圆行

java - 如何设置 java.sql.Timestamp UTC 时间?

使用 PyTables 和 HDF5 进行 Python 单元测试

python - pytest:以 DRY 方式参数化装置