在Mockito 2.2中我用什么代替Whitebox来设置字段? [英] What do I use instead of Whitebox in Mockito 2.2 to set fields?

查看:1865
本文介绍了在Mockito 2.2中我用什么代替Whitebox来设置字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用Mockito 1.9.x时,我一直在使用 Whitebox 来设置字段值以注入模拟。以下示例:

When using Mockito 1.9.x I have been using Whiteboxto set values of fields to "inject" mocks. Se example below:

@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中找到。

I really like this approach, but now that I tried to upgrade to Mockito 2.2.7 I noticed (or rather, my IDE noticed and told me quite a few times) that Whitebox was no longer to be found in Mockito.

我找到了一个替代品,它可以作为替代品,而且是 org.powermock。 reflect.Whitebox ,问题在于我得到了另一个依赖项(Powermock),只是为了使用Whitebox。

I have found one alternative, that can work as a replacement, and that is org.powermock.reflect.Whitebox, the problem with that is that I get another dependency (Powermock), just to use Whitebox.

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

Powermock also have a class named Whitebox, but unfortunately it looks as if it can not be used with Mockito 2.2.x

Mockito有什么好的选择我可以用来手动注入字段,现在 Whitebox 不再可用?

Is there any good alternatives in Mockito that I can use to manually "inject" fields, now that Whitebox is no longer available?

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

I wrote in a comment in response to the post made of @JeffBowman. In short I chose to copy the code of WhiteBox, and use that, since it is used in most of the test cases and the class does not have dependencies to other classes. It was the fastest path to solve this issue.

注意 @bcody建议的解决方案是更好的选择,如果你使用spring,它广告没有额外的代码供您维护。我得到的信息很晚了:(

Note The solution that @bcody suggest is a better alternative, if you are using spring, it ads no extra code for you to maintain. I got that information to late :(

推荐答案

请注意 Whitebox 是始终在 org.mockito.internal 包中。除了主要版本号的增加之外,内部指定是一个赠品包装可能会发生重大变化。

Note that Whitebox was always in the org.mockito.internal package. Beyond the incrementing of the major version number, the internal designation is a giveaway that the package may be subject to breaking changes.

如果您确实希望在测试中设置其他不可访问的字段,您可以在与 setInternalState 一样,只是为了识别层次结构中的字段,在其上调用 setAccessible ,并且然后设置它。完整代码在grepcode上。你还可以查看一些在测试中设置无法访问状态的其他方法

If you do want to make it a point to set otherwise-inaccessible fields in your test, you can do so in the same way that setInternalState does, which is just to identify the field in the hierarchy, call setAccessible on it, and then set it. The full code is here on grepcode. You can also examine a number of other ways to set inaccessible state in tests.

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包中,你通常甚至可以使字段或方法/构造函数包为private,这也是设置并行源文件夹的一个很好的理由 src 测试(等)代表同一Java包的两半。

However, in situations like this, my general advice is to stop fighting the tools: Java's four levels of encapsulation (public, protected, package, private) are not necessarily granular enough to express the degree of protection you're trying to express, and it's often much easier to add a well-documented initialization method or constructor override to override the dependencies as you're trying to do reflectively. If you put your tests in the same Java package as the class it tests, you can often even make the fields or method/constructor package-private, which is also a good reason to set up parallel source folders src and tests (etc) that represent two halves of the same Java package.

虽然有些人将这种额外的方法或构造函数视为API污染,但我认为它可以编码满足您的一个类最重要的消费者 - 自己的测试的要求。如果您需要一个原始的外部界面,您可以轻松地单独定义一个,以便您可以隐藏任何您想要的细节。但是,您可能会发现喜欢能够将任何实际或模拟实现直接注入到您现在更灵活的组件中,此时您可能需要查看依赖注入模式或框架。

Though some treat this additional method or constructor as "API pollution", I see it instead as coding to the requirements of one of your class's most important consumers—its own test. If you need a pristine external interface, you can easily define one separately such that you can hide any details you'd like. However, you may find you like the ability to inject any real or mock implementation directly into your now-more-flexible component, at which point you may want to look into dependency injection patterns or frameworks.

这篇关于在Mockito 2.2中我用什么代替Whitebox来设置字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆