【问题标题】:Verifiyng behavior of mock type without instance controlling在没有实例控制的情况下验证模拟类型的行为
【发布时间】:2014-11-07 15:17:31
【问题描述】:

我正在为内部目的开发 JUnit 的自定义运行程序,例如,我为测试方法引入了自定义注释,在应用时应该使我的运行程序在没有此注释的所有其他测试方法之后运行具有此注释的方法。

我想编写 junit 测试来验证我的自定义跑步者的行为。

测试类:

public class TestClass {
    @Test
    @CustomAnnotation
    public void test1() {
        System.out.println("test1");
    }

    @Test
    public void test2() {
       System.out.println("test2");
    }
}

将测试我的跑步者的抽象代码:

public class MyCustomRunnerTest {
    @Test
    public void order() throws InitializationError {
        // Arrange
        // Some code of mocking library might be placed here

        // Act
        MyCustomRunner runner = new MyCustomRunner(TestClass.class);
        runner.run(new RunNotifier());

        // Assert
        // Here I want to verify that method test1() has been called
        // after method test2()
    }
}

是否有任何模拟库可以让我执行此类验证?或者有没有其他方法可以检查?

【问题讨论】:

    标签: java unit-testing junit mocking


    【解决方案1】:

    为什么不将决定测试方法运行顺序的逻辑提取到单独的类或方法中呢?此方法应返回测试方法名称(或其他描述符)的列表,按它们运行的​​顺序。然后您的测试将归结为将测试类传递给它并断言输出是{“test2”,“test1”}。无需模拟。

    更好的解决方案

    使用 RunListener 记录运行程序正在运行的测试方法。您当然会有自己的 MyCustomRunner 类,但其余代码可以保留在下面的示例中:

    import static org.hamcrest.Matchers.contains;
    import static org.junit.Assert.assertThat;
    
    import java.util.ArrayList;
    import java.util.Collection;
    
    import org.junit.Test;
    import org.junit.runner.Description;
    import org.junit.runner.RunWith;
    import org.junit.runner.notification.RunListener;
    import org.junit.runner.notification.RunNotifier;
    import org.junit.runners.BlockJUnit4ClassRunner;
    import org.junit.runners.model.InitializationError;
    
    @RunWith(BlockJUnit4ClassRunner.class)
    public class RunnerTest {
      // dummy "custom" test runner
      public static class MyCustomRunner extends BlockJUnit4ClassRunner {
        public MyCustomRunner(Class<?> klass) throws InitializationError {
          super(klass);
        }
      }
    
      public static class TestClass {
        @Test
        public void test1() {}
    
        @Test
        public void test2() {}
      }
    
      @Test
      public void myCustomRunnerExecutesTestsInOrder() throws InitializationError {
        RunNotifier notifier = new RunNotifier();
        Collection<String> runTestMethods = new ArrayList<>();
        notifier.addListener(new RunListener() {
          @Override
          public void testStarted(Description description) throws Exception {
            runTestMethods.add(description.getMethodName());
          }
        });
    
        new MyCustomRunner(TestClass.class).run(notifier);
        // assert that the collection contains methods names in the specified order
        assertThat(runTestMethods, contains("test1", "test2"));
      }
    }
    

    【讨论】:

    • 是的,这是我目前的解决方案。只需捕获我的测试类的标准输出并将其与预期的字符串进行比较。但是我想避免这种情况,并尝试通过一些更正确的方式来执行此验证。那么你认为这个任务是可以接受的解决方案并且不需要任何模拟库吗?
    • 不需要模拟。捕获输出是执行此操作的一种方法,但 JUnit 实际上为检查测试运行进度提供了很好的工具。查看我的更新回复。
    • 很好,它比仅仅捕获执行输出更干净和正确。
    猜你喜欢
    • 1970-01-01
    • 2011-04-18
    • 2012-05-01
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    相关资源
    最近更新 更多