【问题标题】:How to create a mock spring bean for a class having autowired dependencies如何为具有自动装配依赖关系的类创建模拟 spring bean
【发布时间】:2015-10-28 12:36:03
【问题描述】:

假设我有一个名为 MainClass 的类。

public class MainClass {
    @Autowired
    AutoWiredClass autoWiredClass;
}

我正在尝试使用 Mockito 创建 MainClass 的模拟 bean。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class AutowiringTest {
    @Configuration
    static class AutowiringTestConfiguration{

        @Bean
        public MainClass mainClass() {
            return Mockito.mock(MainClass.class);
        }
    }

    @Autowired
    MainClass mainClass;

    @Test
    public void testBeanCreation(){
        assertNotNull(mainClass);
    }
}

我在运行测试用例时遇到此错误。

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: autowiring.AutoWiredClass autowiring.MainClass.autoWiredClass; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [autowiring.AutoWiredClass] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我知道我可以使用@Mock 和@InjectMocks 来实现这一点。但这不是我想要的解决方案。

我的要求是创建 MainClass 的模拟 bean,而不创建 AutowiredClass 的实际 bean。请帮助我如何实现这一目标。

【问题讨论】:

  • 如果你只想创建一个 MainClass 的模拟,你需要整个 Spring 的东西做什么?无论如何,模拟不会包含任何其他内容...
  • 我只是举了一个例子。我有一个用例,我要测试的类有多个 @Autowired 字段。我希望其中一些来自春天,而另一些则被嘲笑。
  • 但是在那种情况下,主类本身不能是mock,这里似乎是这样。您可以将模拟放入非模拟中,但反过来不会经常发生并且会更困难一些,可能需要一个 Answer 对象来重定向一些对模拟的调用和一些对真实对象的调用。跨度>
  • @FlorianSchaetz,是的。在我的用例中 MainClass 不是一个模拟。 Mainclass 中的一些依赖项需要被模拟。我举了这个例子来简化问题。如果这个问题得到解答,我的用例也将实现。
  • 在这种情况下,让您的 MainClass 使用构造函数或 setter 注入,然后 @Autowired 您需要自动装配到测试用例中的对象,创建模拟并使用所有这些对象手动构造 MainClass 的实例。

标签: java spring unit-testing junit mocking


【解决方案1】:

正如 Florian 已经评论的那样,您应该尝试创建根本不需要 Spring 的测试,并且您不会遇到这些问题。

但是,如果没有可能的解决方法,您可以对AutoMockRegistryPostProcessor 使用一点魔法。

您只需将AutoMockRegistryPostProcessor 添加到@ContextConfiguration,它就会为您缺少的依赖项创建模拟:

@ContextConfiguration(classes = { AutowiringTest.class, AutoMockRegistryPostProcessor.class })
public class AutowiringTest {
    // no complains anymore, a mockito mock will be created for AutoWiredClass

AutoMockRegistryPostProcessor 类不在 maven 中,您需要将其复制到您的项目中。

文档是here

【讨论】:

  • 这不起作用。 MainClass bean 未由后处理器处理。 String [] beanNames = registry.getBeanDefinitionNames(); System.out.println(Arrays.toString(beanNames));结果没有mainClass作为bean之一。
  • 这是 print 语句的结果。 [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, autowiringTest, autoMockRegistryPostProcessor, org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor, org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor]
  • 成功了。我忘了在@ContextConfiguration 中添加 AutowiringTest.class。但我可以知道为什么需要这样做吗? Mainclass bean 也已经在创建时没有进行这种更改。
  • 一个空的@ContextConfiguration 尝试自己查找配置类,它会找到您的AutowiringTestConfiguration。只要你在@ContextConfiguration中指定一个类(并且需要添加AutoMockRegistryPostProcessor),你就覆盖了自动发现,需要自己显式添加配置类。
  • @Ruben 你的AutoMockRegistryPostProcessor 没有解决Qualifier 的依赖。需要一点修复。你救了我的命,所以非常感谢。
猜你喜欢
  • 2014-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
相关资源
最近更新 更多