【问题标题】:Testing Spring: Avoid injections into mocked objects with Mockito测试 Spring:避免使用 Mockito 注入模拟对象
【发布时间】:2014-04-16 07:26:45
【问题描述】:

问题是:我有一个相当复杂的类B,其中定义了很多@Inject(其中有一个类C)。这个类的一个实例被注入到另一个我想要测试的类 A 中。 这个想法是我想将 B 类的模拟注入 A - 我希望它由 spring 注入,以便在实例之后执行 init 方法已创建(因此这里没有 @InjectMock 进行替代注入)。

Here's an example that is boiled down to three classes Bla, Blub and Blublub。我想要做的是模拟 Blub 并将这个实例注入 BlubBlub - 我想忽略 Bla 的存在。

*已编辑*

主要的一点是,我希望上下文由 Blub 类的模拟和 BlubBlub 类的实例组成。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MockInjectionTest.TestApp.class)
public class MockInjectionTest {
@Inject
public Blub blub;

@Inject
public BlubBlub blubblub;

@Configuration
public static class TestApp {
    @Bean
    Blub getBlub() {
        return mock(Blub.class);
    }

    @Bean
    BlubBlub getBlubBlub() {
        return new BlubBlub();
    }
}

@Test
public void testBlub() {
    Assert.assertNotNull(blub);
}

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

// the classes
public static class Bla {
}

public static class Blub {
    @Inject
    public Bla bla;
}

private static class BlubBlub {
    @Inject
    public Blub blub;
}
}

问题:当我通过使用 @Mock 或通过在 @Bean 方法中显式调用 mock(Blub) 定义 Blub 的模拟时,当 ApplicationContext 被实例化时,我收到以下错误(不管我是使用 xml-config 还是基于注解的 bean 定义)。

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'getBlub': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: public Bla Blub.bla;

显然 Spring 仍然希望实例化原始类,而不是仅仅采用我提供的实例。这个接缝是创建上下文所必需的(如果我手动创建上下文并使用 ctx.getBean() 拉动 bean,它已经在上下文构造中转储)。

来自 Guice,我将我的模拟实例简单地绑定到模块中,一切都会好起来的。

非常感谢您的帮助 - 听起来像是一个标准问题,但我找不到简单的解决方案。

谢谢你,弗里克

【问题讨论】:

标签: java spring unit-testing dependency-injection mockito


【解决方案1】:

将您的配置更改为

@Configuration
public static class TestApp {

@Bean
Blub getBlub() {
    return mock(Blub.class);
}

@Bean
BlubBlub getBlubBlub() {
    return new BlubBlub();
}

@Bean
Bla getBla() {
   return mock(Bla.class)
}

}

Spring 抱怨的是应用程序上下文中没有 Bla 实现,因此无法执行注入

【讨论】:

  • 嗨@geoand,感谢您的快速回复;我是这样的,但假设我有十个这样的 Bla 类应该被注入,那么我最终会得到大量的“纯”样板,这只是因为 Spring 拉动东西而需要的进入我不想在那里的上下文。毕竟他们甚至没有被注射。我希望上下文由 Blub 类的模拟和 BlubBlub 类的实例组成。也许这对于 Spring 是不可能的,这是坚持使用 Guice 的好处之一。
  • 这是个好问题。如果是这种情况,您应该检查 Springockito 项目,该项目几乎可以像您习惯的 @InjectMock 一样工作。 stackoverflow.com/q/19354473/2504224
  • 嗨@geoand,不幸的是Springockito确实帮助解决了Spring在构建上下文时检查所有“@Inject-ed”的类的问题。它在那里中断了。
  • 嗨@geoand,就像我声明“@ReplaceWithMock”@Inject private MyBean innerBean; Springockito 扫描 MyBean 类,如果 MyBean 有“@Inject-ed 未在上下文中声明的类(如上),则上下文的构造中止。
【解决方案2】:

你可以像这样返回一个空 bean:

@Configuration
public static class TestApp {
    @Bean
    Blub getBlub() {
        return mock(Blub.class);
    }
    @Bean
    Bla getBla() {
        return null;
    }

    @Bean
    BlubBlub getBlubBlub() {
        return new BlubBlub();
    }
}

这将避免注入 Bla 实例,因为没有。 当您有许多 @Injects 时,这并不理想,但这是可行的。

另一个也不理想的解决方案是让你的 bean 实现一个接口,并模拟接口而不是实现类。

我尝试了 springockito,这适用于您的情况,但是在我的一个测试用例中,它是关于测试自定义 BeanDefinitionRegistryPostProcessor 的,它在很多正常的弹簧行为中都被认为是混乱的。

【讨论】:

    猜你喜欢
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-11
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多