【问题标题】:Tests order dependency due to constant (final) fields测试由于常量(最终)字段而导致的订单依赖性
【发布时间】:2015-06-01 23:30:37
【问题描述】:

修改单元测试常量的推荐模式是什么?这是我目前使用的一段时间,今天我意识到它有缺陷。

假设我的班级看起来像这样

class Foo {
   private static final int MAX_TIME = Integer.getInteger("myProp", 1000);
   ...
}

我使用 VM 属性的事实不仅仅是在单元测试中修改它。这是因为我希望它在实际代码中是不可变的,并且我不想用它污染构造函数,因为它是一个实现细节。

所以,在生产中我想要 1 秒的超时时间;但是这对于单元测试来说太长了,所以我这样做了

class FooTest {
   @Before
   public void setUp() {
      System.setProperty("myProp", "50");
   }
   @Test
   public void testThatAssumesTimeoutOf50() { ... }
}

这工作了很长时间,直到今天我终于像这样添加了BarTest

class BarTest {
   Foo mockFoo = mock(Foo.class); //actually done in a @Before method in the real code
}

现在,这会导致我的测试失败或通过,具体取决于执行顺序。如果首先测试Foo,则假设测试超时为 50 毫秒的测试通过。但是如果首先测试Bar,那么这会使Foo由于模拟而被加载,所以MAX_TIME采用默认值1000,然后当BarTest结束并且FooTest开始时,假设测试的测试50 毫秒的超时现在失败。

【问题讨论】:

  • 每个类的测试应该是独立的。有一些方法可以在类中强制执行顺序。

标签: java unit-testing junit testng


【解决方案1】:

最简单的方法可能是删除final 关键字。这将允许您在类加载时间之后更改值。

由于您在许多不同的类和可能的包中设置和获取值,因此您可能应该添加一个 getter 和 setter。如果您需要跨包更改此值,则必须为 public

 class Foo{

   public static int getMaxTime(){
        return MAX_TIME;
   }

   public static  void changeMaxTime(int timeout){
        //validation logic goes here
        this.MAX_TIME = timeout;
   }

然后,在您的测试类中,您应该将旧值保存在@BeforeClass@Before 阶段,将其更改为您想要的任何值,然后在@AfterClass@After 阶段恢复旧值.

由于您似乎在许多测试课程中都这样做,因此最好自己创建Test Rule

 public class TimeoutRule extends ExternalResource {

   private final int oldTimeout, newTimeout;

   public TimeoutRule(int timeout){
         this.oldTimeout = Foo.getMaxTime();
         this.newTimeout = timeout;
   }

    @Override
    protected void before() {

    }

   @Override
   protected void after() {
       //restore old timeout
        Foo.setMaxTimeOut(oldTimeout);
}

}

然后在你的测试代码中:

class FooTest {

  @Rule
  public TimeoutRule timeoutRule = new TimeoutRule(50);

  @Test
  public void testThatAssumesTimeoutOf50() { ... }

}

该代码会将超时重置为 50 毫秒,然后在每次测试后将其恢复为原始值。如果您只想在每个测试类中执行一次,请改用@ClassRule(并将字段设为static

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 2016-08-20
    相关资源
    最近更新 更多