在不设置原始状态的情况下撤消@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);
}

那么testAtestB可以保持相同的代码。并且突变测试仍将覆盖 ObjectMapper 属性声明,如图所示: