在JUnit测试子类中引用受保护变量时出现空指针异常。

huangapple go评论78阅读模式
英文:

Getting NullPointerException in reference to protected variable in JUnit Test subclass

问题

我有一个名为 AnswerQuestionTests 的子类,其中包含几个带有 @Test 注解的 JUnit 测试(我正在运行 JUnit 4)。这个子类继承自一个名为 TestBase 的超类,该超类没有其他测试方法,但包含一些 protected 访问修饰符的变量。我们的想法是,为了减少代码重复,我们希望所有的测试都扩展自 TestBase,以避免在大多数测试中重复代码以初始化一些模拟服务。

例如,我在 AnswerQuestionTests 中有一个方法,测试徽章的进度是否在数据库中递增:

@Test
public void testBadgeProgressIncremented() {
    int badgeProgressBeforeAction = clientModule.badgeClient().getCurrentBadgeActivity();
    ...
}

在这种情况下,clientModule 是在超类 TestBase 中声明的 protected 变量。这个变量在 TestBase 中的 initialize() 方法中进行初始化,然后在 AnswerQuestionTests 中使用 @BeforeAll 注解调用该方法:

public class AnswerQuestionTests extends TestBase {
    @BeforeAll
    public void initialize() {
        super.initialize();
    }
    ...
}

我使用 Bazel 的 java_test 规则来运行这个测试,它将 test_class 作为参数,我给它传递了 AnswerQuestionTest 类。然而,运行器在引用超类中声明的 clientModule 和所有其他 protected 变量时会产生 NullPointerException

我猜想这可能与我对 JUnit 运行器工作方式的了解不足有关,但是否有人能提供一些建议?

编辑:我还使用 @TestInstance(Lifecycle.PER_CLASS) 注解了 AnswerQuestionTests,以便 JUnit 运行器每个类只创建一个新实例,而不是每个方法创建一个新实例。

编辑 2:问题是 Bazel 的 java_test 运行器本质上是运行 JUnit 4,但我们所有的测试先前都是基于使用 JUnit 5 的假设编写的。已解决。

英文:

I have a subclass AnswerQuestionTests which contains several JUnit tests annotated with @Test (I'm running JUnit 4). This subclass extends a superclass TestBase which has no other test methods, but contains a bunch of protected variables. The idea we had was that, in order to reduce code duplication, we would have all of our tests extend TestBase to avoid duplicating code for initialization of some mocked services that most of our tests need.

For example, I have a method in AnswerQuestionTests which tests whether or not a badge's progress gets incremented in the database:

@Test
public void testBadgeProgressIncremented() {
    int badgeProgressBeforeAction = clientModule.badgeClient().getCurrentBadgeActivity();
    ...
}

In this case, clientModule is a protected variable which is declared in the superclass TestBase. This variable gets initialized in an initialize() method in TestBase, which is called from AnswerQuestionTests using a @BeforeAll annotation:

public class AnswerQuestionTests extends TestBase {
    @BeforeAll
    public void initialize() {
        super.initialize();
    }
    ...
}

I run this test using Bazel's java_test rule, which takes a test_class as a parameter, and I give it the AnswerQuestionTest class. However, the runner produces a NullPointerException in reference to clientModule and all of the other protected variables declared in the superclass.

I assume this has something to do with my lack of knowledge about how the JUnit runner works, but can anybody offer any advice?

EDIT: I also annotate AnswerQuestionTests with @TestInstance(Lifecycle.PER_CLASS) so that the JUnit runner only creates a new instance once per class instead of once per method.

EDIT 2: The issue was that the Bazel java_test runner natively runs JUnit4, but all of our tests were previously written under the assumption of using JUnit5. Resolved.

答案1

得分: 1

在JUnit4中,此注释称为@BeforeClass,应该用于一个static方法上。它会在执行此类中的所有测试方法之前执行。JUnit5的注释将在JUnit4中被忽略。

对于每个方法的执行,JUnit会创建一个AnswerQuestionTests的新实例,因此您不能在@BeforeClass中使用实例字段。

一个选择是将初始化的客户端存储在一个静态字段中。

英文:

In junit4 this annotation is called @BeforeClass and should be on a static method. It is executed before all test methods in this class are executed. Junit5 annotation will be ignored in junit4

For each method execution Junit creates a new instance of AnswerQuestionTests, so you can't use instance fields in @BeforeClass.

One option would be to store the initialized client in a static field.

huangapple
  • 本文由 发表于 2020年4月6日 07:25:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/61050823.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定