为什么字段变量在 JUnitParams 方法中设置后为空?
Why are field variables null after setting them in JUnitParams method?
我正在使用 JUnitParams
和 Mockito
编写测试 class。我想将 Mockito mock
用作 parameter
。在我的测试中,我有大约十个模拟,我只想传递一个模拟来为其定义特殊行为。
我在一个简单的例子中重现了这个问题。
我的问题:我在方法parametersForTest
中初始化变量myList
,但是当我调试到test
方法时myList
为null,但是param
是我想要的模拟。
@RunWith(JUnitParamsRunner.class)
public class MockitoJUnitParamsTest {
private List myList;
@Test
@Parameters
public void test(List param) {
assertThat(param).isEqualTo(this.myList);
}
public Object[] parametersForTest() {
myList = Mockito.mock(List.class);
return new Object[]{myList};
}
}
我用
- JUnitParams 版本 1.0.5
- JUnit 版本 4.12
- Mockito 版本 1.10.19
为什么 myList 为空,我该如何解决?
MockitoJUnitParamsTest 实例 class 运行ning parametersForTest() 方法与 运行ning test() 不同。这是因为 Junit 会为每个测试方法创建不同的实例。
在你的情况下,使 myList 静态
private static List myList;
可以部分解决问题,但并行测试运行可能会失败。
JUnit 框架和 运行 开发人员经常为每个方法调用创建单独的测试实例 class。看起来这就是 JUnitParams 所做的 - 您可以使用以下测试看到:
@RunWith(JUnitParamsRunner.class)
public class JUnitParamsTest {
@Test
@Parameters
public void test(JUnitParamsTest param) {
Assert.assertNotNull(param);
Assert.assertNotSame(this, param);
}
Object[] parametersForTest() {
return new Object[]{this};
}
}
所以上面示例的问题在于 parametersForTest
设置的 myList
字段是与调用 test(List)
的对象不同的对象的成员。
如何修复
嗯,我想关键问题是,你想在这里实现什么? JUnitParams 的整个点 是参数被注入到测试方法中,因此您不必使用字段。在我看来,在 parametersForTest()
方法中修改字段值超出了预期用途,我真的不明白你为什么要这样做。
一个快速而肮脏的修复方法是使 myList
静态化,只要您的测试 class 没有被多个线程同时访问(一些单元测试环境会 运行多线程所以这里有风险)。
更好的解决方案是重新设计您的测试,这样您就不会从参数生成方法内部修改字段。您给出的示例似乎没有尝试测试 JUnitParams 本身以外的任何内容,因此我无法帮助您确定什么是好的设计,因为我不知道您要实现什么。你是说你想要几个测试方法来 共享 一个 Mockito 模拟?如果是这样,为什么?我不确定 Mockito 会支持这个(我没试过)。单元测试通常应该相互隔离,因此建议的操作是每次都创建一个新的模拟。
我正在使用 JUnitParams
和 Mockito
编写测试 class。我想将 Mockito mock
用作 parameter
。在我的测试中,我有大约十个模拟,我只想传递一个模拟来为其定义特殊行为。
我在一个简单的例子中重现了这个问题。
我的问题:我在方法parametersForTest
中初始化变量myList
,但是当我调试到test
方法时myList
为null,但是param
是我想要的模拟。
@RunWith(JUnitParamsRunner.class)
public class MockitoJUnitParamsTest {
private List myList;
@Test
@Parameters
public void test(List param) {
assertThat(param).isEqualTo(this.myList);
}
public Object[] parametersForTest() {
myList = Mockito.mock(List.class);
return new Object[]{myList};
}
}
我用
- JUnitParams 版本 1.0.5
- JUnit 版本 4.12
- Mockito 版本 1.10.19
为什么 myList 为空,我该如何解决?
MockitoJUnitParamsTest 实例 class 运行ning parametersForTest() 方法与 运行ning test() 不同。这是因为 Junit 会为每个测试方法创建不同的实例。 在你的情况下,使 myList 静态
private static List myList;
可以部分解决问题,但并行测试运行可能会失败。
JUnit 框架和 运行 开发人员经常为每个方法调用创建单独的测试实例 class。看起来这就是 JUnitParams 所做的 - 您可以使用以下测试看到:
@RunWith(JUnitParamsRunner.class)
public class JUnitParamsTest {
@Test
@Parameters
public void test(JUnitParamsTest param) {
Assert.assertNotNull(param);
Assert.assertNotSame(this, param);
}
Object[] parametersForTest() {
return new Object[]{this};
}
}
所以上面示例的问题在于 parametersForTest
设置的 myList
字段是与调用 test(List)
的对象不同的对象的成员。
如何修复
嗯,我想关键问题是,你想在这里实现什么? JUnitParams 的整个点 是参数被注入到测试方法中,因此您不必使用字段。在我看来,在 parametersForTest()
方法中修改字段值超出了预期用途,我真的不明白你为什么要这样做。
一个快速而肮脏的修复方法是使 myList
静态化,只要您的测试 class 没有被多个线程同时访问(一些单元测试环境会 运行多线程所以这里有风险)。
更好的解决方案是重新设计您的测试,这样您就不会从参数生成方法内部修改字段。您给出的示例似乎没有尝试测试 JUnitParams 本身以外的任何内容,因此我无法帮助您确定什么是好的设计,因为我不知道您要实现什么。你是说你想要几个测试方法来 共享 一个 Mockito 模拟?如果是这样,为什么?我不确定 Mockito 会支持这个(我没试过)。单元测试通常应该相互隔离,因此建议的操作是每次都创建一个新的模拟。