JUnit测试中的成员变量

时间:2018-05-06 23:26:53

标签: java junit

我在运行一些单元测试时遇到了一些有趣的事情。我有以下方法:

private void createSchemaIfNecessary() throws SQLException, IOException{
    if(!schemaExists){
         try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement();) {
             statement.execute(getSQLByFileName(GOLF_COURSE_TABLE_CREATION_SCRIPT));
             statement.execute(getSQLByFileName(GOLF_COURSE_HOLE_TABLE_CREATION_SCRIPT));
             connection.commit();
             schemaExists = true;
         }
    }
}

每个单元测试都会调用此方法来确定是否创建表。 schemaExists变量是成员变量。我注意到,当每个测试都在运行时,有些情况下即使在点击schemaExists = true;行之后,下次调用该方法时,schemaExists也会被评估为false。然后我将变量设为静态,这解决了问题。

由于单个单元测试正在运行,它们是否都在单元测试类的单个实例的上下文中运行?

1 个答案:

答案 0 :(得分:3)

我将假设schemaExists是您的测试类的非静态成员。

在调用测试方法(带注释的@Test)之前,junit(默认情况下)会创建测试类的新实例(More detail here)。

因此,任何非静态类成员都将根据类中的定义进行初始化。如果未显式初始化,则它们将被设置为默认值,因此如果schemaExistsboolean(原语)然后false

如果你想为所有要分享的测试设置一些内容,我建议你想要做的是创建一个@BeforeClass静态方法来初始化静态属性。

  • 这将确保在运行任何测试方法之前,它只对给定的测试类运行一次
  • 其他人在阅读您的代码时非常清楚该方法的意图是什么

以下是OP中数据库架构初始化代码的示例:

@BeforeClass 
public static void setupDBOnce() {
   Connection connection = dataSource.getConnection(); 
   Statement statement = connection.createStatement();  
   statement.execute(getSQLByFileName(GOLF_COURSE_TABLE_CREATION_SCRIPT));
   statement.execute(getSQLByFileName(GOLF_COURSE_HOLE_TABLE_CREATION_SCRIPT));
   connection.commit();
 }

如果由于某种原因你不想要这种行为(每个测试方法运行一个实例)you can do any of these

  • 使用@TestInstance(Lifecycle.PER_CLASS)
  • 为您的班级添加注释
  • 传递以下VM arg:-Djunit.jupiter.testinstance.lifecycle.default=per_class
  • 创建或添加到类路径的源根目录中找到的名为junit-platform.properties的现有属性文件:junit.jupiter.testinstance.lifecycle.default = per_class

如果你覆盖了默认值,那么值得记住的一个注意事项是:

  

使用此模式时,每个测试类将创建一个新的测试实例。因此,如果您的测试方法依赖于存储在实例变量中的状态,则可能需要在@BeforeEach或@AfterEach方法中重置该状态。