在不设置原始状态的情况下撤消@AfterMethod 中的 Whitebox.setInternalState
Undoing Whitebox.setInternalState in a @AfterMethod without setting original state
我有一个 class,由于接口的强制性实现,我不能轻易地使用依赖注入来模拟 - 简而言之,因此我将使用 Whitebox 而我关心的不是与设计相关,相反,它只是想弄清楚如何正确 "tearDown" Whitebox 引起的行为。等一下,我会给你更多细节 - 这是主要的假人 class:
public class Dummy implements MandatoryInterface {
private static final Logger logger = Logger.getLogger(MethodHandles.lookup().lookupClass());
private final ObjectMapper mapper = new ObjectMapper();
@Override
public Object convertArgumentToJson(Object arg) {
if (arg != null) {
try {
return mapper.writeValueAsString(arg);
} catch (IOException e) {
// doSomething();
logger.error("Error tracking request", e);
}
}
return null;
}
}
假设我想涵盖如果这里发生异常会发生什么,我看到的唯一方法是使用 Whitebox.setInternalState。这里是测试:
public class DummyTest {
private Dummy dummy = new Dummy();
@Test
public void testA() throws IOException {
final ObjectMapper mock = Mockito.mock(ObjectMapper.class);
Whitebox.setInternalState(dummy, "mapper", mock);
Mockito.when(mock.writeValueAsString(Mockito.any()))
.thenThrow(new IOException());
Assert.assertNull(dummy.convertArgumentToJson("testA"));
}
@Test
public void testB() {
Assert.assertNotNull(dummy.convertArgumentToJson("testB"));
}
}
如您所见,我无法将 Dummy class 中的映射器定义为静态的,因为有 Whitebox(它不起作用)。
话虽如此,在执行 testA() 之后,我们模拟了映射器:
问题是:在执行 testB 时,我不再需要 mock - 它应该是最初包含在 Dummy 中的旧实例化 ObjectMapper。但是出现的是:
现在,我的问题是:
撤消
的正确方法是什么
Whitebox.setInternalState(dummy, "mapper", mock);
P.S.: 我考虑过像这样使用 tearDown():
@AfterMethod
public void tearDown(){
Whitebox.setInternalState(dummy, "mapper", originalState);
}
但是,在这种情况下,我的 pitest(变异测试)会认为我没有涵盖 ObjectMapper 的初始化,所以:有没有一种方法可以在不手动设置的情况下为其余测试撤消 Whitebox旧的?
抱歉,描述太长了,提前致谢。
此致,
对不起各位,我成功了。
为了防止其他人遇到同样的问题,答案比我想象的要简单。
private static final String MAPPER_DESC = "mapper";
private ObjectMapper originalMapper;
@BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
originalMapper = (ObjectMapper) Whitebox.getInternalState(converter, MAPPER_DESC);
}
@AfterMethod
public void tearDown() {
Whitebox.setInternalState(converter, MAPPER_DESC, originalMapper);
}
那么testA和testB可以保持相同的代码。并且突变测试仍将覆盖 ObjectMapper 属性声明,如图所示:
我有一个 class,由于接口的强制性实现,我不能轻易地使用依赖注入来模拟 - 简而言之,因此我将使用 Whitebox 而我关心的不是与设计相关,相反,它只是想弄清楚如何正确 "tearDown" Whitebox 引起的行为。等一下,我会给你更多细节 - 这是主要的假人 class:
public class Dummy implements MandatoryInterface {
private static final Logger logger = Logger.getLogger(MethodHandles.lookup().lookupClass());
private final ObjectMapper mapper = new ObjectMapper();
@Override
public Object convertArgumentToJson(Object arg) {
if (arg != null) {
try {
return mapper.writeValueAsString(arg);
} catch (IOException e) {
// doSomething();
logger.error("Error tracking request", e);
}
}
return null;
}
}
假设我想涵盖如果这里发生异常会发生什么,我看到的唯一方法是使用 Whitebox.setInternalState。这里是测试:
public class DummyTest {
private Dummy dummy = new Dummy();
@Test
public void testA() throws IOException {
final ObjectMapper mock = Mockito.mock(ObjectMapper.class);
Whitebox.setInternalState(dummy, "mapper", mock);
Mockito.when(mock.writeValueAsString(Mockito.any()))
.thenThrow(new IOException());
Assert.assertNull(dummy.convertArgumentToJson("testA"));
}
@Test
public void testB() {
Assert.assertNotNull(dummy.convertArgumentToJson("testB"));
}
}
如您所见,我无法将 Dummy class 中的映射器定义为静态的,因为有 Whitebox(它不起作用)。 话虽如此,在执行 testA() 之后,我们模拟了映射器:
问题是:在执行 testB 时,我不再需要 mock - 它应该是最初包含在 Dummy 中的旧实例化 ObjectMapper。但是出现的是:
现在,我的问题是:
撤消
的正确方法是什么 Whitebox.setInternalState(dummy, "mapper", mock);
P.S.: 我考虑过像这样使用 tearDown():
@AfterMethod
public void tearDown(){
Whitebox.setInternalState(dummy, "mapper", originalState);
}
但是,在这种情况下,我的 pitest(变异测试)会认为我没有涵盖 ObjectMapper 的初始化,所以:有没有一种方法可以在不手动设置的情况下为其余测试撤消 Whitebox旧的?
抱歉,描述太长了,提前致谢。
此致,
对不起各位,我成功了。
为了防止其他人遇到同样的问题,答案比我想象的要简单。
private static final String MAPPER_DESC = "mapper";
private ObjectMapper originalMapper;
@BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
originalMapper = (ObjectMapper) Whitebox.getInternalState(converter, MAPPER_DESC);
}
@AfterMethod
public void tearDown() {
Whitebox.setInternalState(converter, MAPPER_DESC, originalMapper);
}
那么testA和testB可以保持相同的代码。并且突变测试仍将覆盖 ObjectMapper 属性声明,如图所示: