当前位置: 首页 > 面试题库 >

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

强金鑫
2023-03-14
问题内容

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

@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并告诉我很多次),在Mockito中不再找到Whitebox。

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

Powermock也有一个名为的类Whitebox,但不幸的是,它看起来无法与Mockito 2.2.x

在Mockito中,有什么好的替代方法可以用来手动“注入”字段,而现在这些替代方法Whitebox不再可用了?

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

注意 @bcody建议的解决方案是更好的选择,如果您使用的是spring,则它不会增加任何代码供您维护。我知道这些信息了:(


问题答案:

请注意,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污染”,但我认为它是按照类中最重要的使用者之一的要求(即 自己的测试)进行
编码。如果您需要原始的外部接口,则可以轻松地单独定义一个接口,以便隐藏所需的任何细节。但是,您可能会发现自己 喜欢
将任何实际或模拟的实现直接注入到您现在更灵活的组件中的能力,此时,您可能希望研究依赖项注入模式或框架



 类似资料:
  • 问题内容: 所以我查看了一些Java代码并偶然发现: 基本上,此列表接受所有属于SomeObject的对象- SomeObject本身或其继承者。但是根据多态性,它的继承者也可以看作是SomeObject,因此它也可以工作: 那么,为什么在第二个选项定义明确且基本相同时,有人会使用第一个选项呢? 问题答案: 在这种情况下,您不能说( 不允许 )在哪里 你可以说 ( 允许 ) 但是请注意,您 不能在

  • 问题内容: 看看这个: 我运行了一个快速的Google搜索,但找不到答案- 我应该用什么代替? 问题答案: 由于django 1.7 引入的迁移系统而被弃用。 现在,您可以使用 跟踪 更改。这会将您的模型更改转换为python代码,以使其可部署到另一个数据库。当您需要对数据库进行进一步的修改时,可以使用数据迁移。 创建迁移后,您必须 应用 它们:。 因此,除了使用之外,您还应该使用然后。 更改模型

  • 问题内容: 看看这个: 问题答案: 由于django 1.7引入的迁移系统而被弃用。 现在,你可以使用跟踪更改。这会将你的模型更改转换为python代码,以使其可部署到另一个数据库。当你需要对数据库进行进一步的修改时,可以使用数据迁移。 创建迁移后,你必须应用它们:。 因此,除了使用之外,你还应该使用然后。 更改模型中的某些内容后,开发工作流程如下: 在你的生产系统上: 奖励:你无需migrate

  • 本文向大家介绍为什么在Bash中应该避免eval,我应该用什么来代替呢?,包括了为什么在Bash中应该避免eval,我应该用什么来代替呢?的使用技巧和注意事项,需要的朋友参考一下 eval是Bash shell的内置命令,它将其参数连接为单个字符串。然后,它将参数与空格连接起来,然后将该字符串作为bash命令执行。以下是其工作方式的示例。 eval示例 在下面的示例中,我们使用一个字符串,该字符串

  • 我试图将代码Kotlin转换为java,但在java中找不到run函数。这是Kotlin代码: 我使用resumeArElementsTask,比如 当我转换为java时 如何在java中使用run函数并将此代码转换为java 谢谢

  • 这个方法有什么用? 我可以用另一种方法替换它以获得相同的结果吗?