在@AfterMethod中撤消Whitebox.setInternalState而不设置原始状态

时间:2018-06-11 09:09:32

标签: unit-testing mockito white-box-testing

我有一个类,由于接口的强制实现,我不能轻易地使用依赖注入来模拟 - 简而言之,因为我将使用Whitebox而我在这里的关注与设计无关,而是它只是想弄清楚如何正确地“撕下”"由Whitebox引起的行为。忍受我一秒钟,我会给你更多细节 - 这是主要的假人类:

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类中的映射器定义为静态,因为Whitebox(它不会起作用)。 话虽如此,在执行 testA()之后,我们已经模拟了映射器:

enter image description here

问题是:当执行 testB 时,我不再需要模拟 - 它应该是最初包含在Dummy中的旧实例化ObjectMapper。但看起来是什么:

enter image description here

现在,我的问题:

撤消

的正确方法是什么
 Whitebox.setInternalState(dummy, "mapper", mock);

P.S。:我考虑过像这样使用tearDown():

@AfterMethod
public void tearDown(){
    Whitebox.setInternalState(dummy, "mapper", originalState);
}

然而,在这种情况下,我的pitest(变异测试)会认为我没有覆盖ObjectMapper的初始化,所以:有没有办法只需要在没有手动设置的情况下撤消其余测试的Whitebox旧的?

对于长篇描述和提前感谢,我们深表歉意。

此致

1 个答案:

答案 0 :(得分:0)

对不起伙计们,我设法得到了它。

万一其他人可能面临同样的问题,答案比我想象的要容易。

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属性声明,如图所示: enter image description here