Java JUnit测试中的成员变量

Java JUnit测试中的成员变量,java,junit,Java,Junit,在运行一些单元测试时,我遇到了一些有趣的事情。我有以下方法: private void createSchemaIfNecessary() throws SQLException, IOException{ if(!schemaExists){ try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement();) {

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

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之后,仍然存在这样的情况
line,下次调用该方法时,
schemaExists
计算为false。然后我将变量设为静态,这就解决了问题


当单个单元测试运行时,它们不是都在单元测试类的单个实例的上下文中运行吗?

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

在调用测试方法(注释为
@test
)之前,junit(默认情况下)创建测试类()的新实例

因此,任何非静态类成员都将按照类中定义的进行初始化,如果没有显式初始化,那么它们将被设置为默认值,因此如果
schemaExists
布尔值
(原语),则
为false

我建议,如果要为所有测试设置共享的内容,您应该创建一个
@BeforeClass
静态方法来初始化静态属性

  • 这将确保在运行任何测试方法之前,对给定的测试类只运行一次
  • 阅读您的代码的其他人非常清楚该方法的意图
下面是OP中DB模式初始化代码的示例:

@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();
 }
如果出于某种原因您不希望出现这种行为(每个测试方法运行一个实例):

  • @TestInstance(Lifecycle.PER_class)
  • 传递以下VM参数:
    -Djunit.jupiter.testinstance.lifecycle.default=per_class
  • 创建名为junit platform.properties的现有属性文件,或将其添加到类路径的源根目录中,条目:
    junit.jupiter.testinstance.lifecycle.default=per_class
如果您确实覆盖了默认值,则需要从文档中记住一个注意事项:

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


我认为正确的方法是设置(使用特定测试所需的数据创建和填充表),然后丢弃所有内容。在您的方法中,如果某些测试同时运行(正如它们应该运行的那样),您可能会遇到竞争条件,除非您在用
@BeforeClass
注释的方法中调用
createSchemaIfNecessary
,否则这在您的情况下是不可能的,因为您的方法不是
静态的,问题是我有安装方法所依赖的spring注入的自连线依赖项,而我无法实现这些依赖项static@user1154644啊,好的,那么看看我的更新——添加了一种强制Junit使用相同实例的方法(而不是每个测试方法使用默认实例)@user1154644是否有任何方法可以更改生命周期?