在 Mockito 2.2 中,我应该使用什么来代替 Whitebox 来设置字段?

2022-09-01 04:48:19

当使用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);
}

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

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

Powermock还有一个名为 的类,但不幸的是,它看起来好像不能与WhiteboxMockito 2.2.x

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


溶液

我在评论中写道,以回应@JeffBowman的帖子。简而言之,我选择复制WhiteBox的代码并使用它,因为它在大多数测试用例中使用,并且该类没有与其他类的依赖关系。这是解决此问题的最快途径。

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


答案 1

如果您使用的是Spring(特别是弹簧测试库),则可以简单地使用而不是ReflectionTestUtils.setFieldWhitebox.setInternalState


答案 2

请注意,这始终在包中。除了增加主要版本号之外,该指定还附带了包可能会发生重大更改。Whiteboxorg.mockito.internalinternal

如果确实希望在测试中设置其他方式无法访问的字段,则可以采用与设置相同的方式执行此操作,即在层次结构中标识字段,调用它,然后进行设置。完整的代码在 grepcode 上。您还可以检查在测试中设置无法访问状态的许多其他方法setInternalStatesetAccessible

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 包中,则通常甚至可以使字段或方法/构造函数包私有,这也是设置并行源文件夹和(等)的一个很好的理由,它们表示同一 Java 包的两半。srctests

虽然有些人将此附加方法或构造函数视为“API 污染”,但我认为它更像是按照类中最重要的使用者之一(它自己的测试)的要求进行编码。如果您需要一个原始的外部接口,您可以轻松地单独定义一个,以便您可以隐藏所需的任何细节。但是,您可能会发现自己喜欢将任何实际或模拟实现直接注入到现在更灵活的组件中的能力,此时您可能希望研究依赖注入模式或框架。


推荐