我用什么代替 Mockito 2.2 中的 Whitebox 来设置字段?

新手上路,请多包涵

使用 Mockito 1.9.x 时,我一直在使用 Whitebox 将字段值设置为“注入”模拟。示例如下:

 @Before
public void setUp() {

    eventHandler = new ProcessEventHandler();
    securityService = new SecurityServiceMock();
    registrationService = mock(RegistrationService.class);

    Whitebox.setInternalState(eventHandler, "registrationService", registrationService);
    Whitebox.setInternalState(eventHandler, "securityService", securityService);
}

我真的很喜欢这种方法,但是现在我尝试升级到 Mockito 2.2.7 我注意到(或者更确切地说,我的 IDE 注意到并告诉我很多次)Whitebox 不再是可以在 Mockito 中找到。

我找到了一个可以替代的替代方案,那就是 org.powermock.reflect.Whitebox ,问题是我得到了另一个依赖项 (Powermock),只是为了使用 Whitebox。

Powermock 也有一个名为 Whitebox 的类,但不幸的是它看起来好像不能与 Mockito 2.2.x 一起使用

现在 Whitebox 不再可用,我可以使用 Mockito 中的任何好的替代方法来手动“注入”字段吗?


解决方案

我在评论中回复了@JeffBowman 的帖子。简而言之,我选择复制 WhiteBox 的代码并使用它,因为它用于大多数测试用例并且该类不依赖于其他类。这是解决这个问题的最快途径。

注意@bcody 建议的解决方案是一个更好的选择,如果您使用的是 spring,它不会为您维护额外的代码。我很晚才得到这些信息:(

原文由 emanciperingsivraren 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

请注意, Whitebox 始终位于 org.mockito.internal 包中。除了主要版本号的递增之外, internal 标志是一个赠品,表明该软件包可能会受到重大更改。

如果您确实想在测试中设置其他不可访问的字段,您可以按照 setInternalState 相同的方式进行操作,这只是为了识别层次结构中的字段,调用 setAccessible 就可以了,然后设置。 完整代码在 grepcode 上。 您还可以检查 在测试中设置不可访问状态的其他一些方法

 public static void setInternalState(Object target, String field, Object value) {
    Class<?> c = target.getClass();
    try {
        Field f = getFieldFromHierarchy(c, field);  // Checks superclasses.
        f.setAccessible(true);
        f.set(target, value);
    } catch (Exception e) {
        throw new RuntimeException(
            "Unable to set internal state on a private field. [...]", e);
    }
}

然而, 在这种情况下,我的一般建议是 _停止与工具作斗争_:Java 的四个封装级别(公共、受保护、包、私有)不一定足够细化以表达您试图表达的保护程度,并且当您试图以反射方式进行操作时,添加一个记录良好的初始化方法或构造函数覆盖来覆盖依赖项通常要容易得多。如果将测试放在与它测试的类相同的 Java 包中,通常甚至可以使字段或方法/构造函数包私有,这也是设置并行源文件夹的一个很好的理由 srctests (等)代表同一个 Java 包的两半。

尽管有些人将这种额外的方法或构造函数视为“API 污染”,但我将其视为编码以满足您的类最重要的消费者之一的要求—— _它自己的测试_。如果您需要一个原始的外部接口,您可以轻松地单独定义一个接口,这样您就可以隐藏任何您想要的细节。然而,您可能会发现自己 喜欢 将任何真实或模拟实现直接注入到现在更灵活的组件中的能力,此时您可能想要研究依赖注入模式或框架。

原文由 Jeff Bowman 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您正在使用 Spring(特别是 spring-test 库),您可以简单地使用 ReflectionTestUtils.setField 而不是 Whitebox.setInternalState

原文由 bcody 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题