首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在应用程序启动之前配置@MockBean组件

在应用程序启动之前配置@MockBean组件
EN

Stack Overflow用户
提问于 2016-11-12 13:36:47
回答 6查看 35.4K关注 0票数 43

我有一个SpringBoot1.4.2应用程序。在启动期间使用的一些代码如下所示:

代码语言:javascript
运行
复制
@Component 
class SystemTypeDetector{
    public enum SystemType{ TYPE_A, TYPE_B, TYPE_C }
    public SystemType getSystemType(){ return ... }
}

@Component 
public class SomeOtherComponent{
    @Autowired 
    private SystemTypeDetector systemTypeDetector;
    @PostConstruct 
    public void startup(){
        switch(systemTypeDetector.getSystemType()){   // <-- NPE here in test
        case TYPE_A: ...
        case TYPE_B: ...
        case TYPE_C: ...
        }
    }
}

有一个组件决定系统类型。此组件在从其他组件启动时使用。在生产中一切都很好。

现在,我想使用Spring1.4的@MockBean添加一些集成测试。

测试结果如下:

代码语言:javascript
运行
复制
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyWebApplication.class, webEnvironment = RANDOM_PORT)
public class IntegrationTestNrOne {
    @MockBean 
    private SystemTypeDetector systemTypeDetectorMock;

    @Before 
    public void initMock(){
       Mockito.when(systemTypeDetectorMock.getSystemType()).thenReturn(TYPE_C);
    }

    @Test 
    public void testNrOne(){
      // ...
    }
}

基本上,嘲弄的效果很好。使用我的systemTypeDetectorMock,如果我调用getSystemType,则返回-> TYPE_C

问题是应用程序没有启动。目前弹簧的工作顺序似乎是:

  1. 创建所有Mocks (没有配置,所有方法都返回null)
  2. 启动应用
  3. 调用@ the方法(其中将配置模拟)
  4. 起动试验

我的问题是,应用程序以未初始化的模拟开始。因此,对getSystemType()的调用返回null。

我的问题是:如何在应用程序启动之前配置模拟?

编辑:,如果某人有同样的问题,一个解决办法就是使用@MockBean(answer = CALLS_REAL_METHODS)。这就调用了真正的组件,在我的例子中,系统启动了。启动后,我可以更改模拟行为。

EN

回答 6

Stack Overflow用户

发布于 2019-10-23 07:09:37

在本例中,您需要以我们在引入@MockBean之前使用的方式配置模拟--通过手动指定一个@Primary bean来替换上下文中的原始bean。

代码语言:javascript
运行
复制
@SpringBootTest
class DemoApplicationTests {

    @TestConfiguration
    public static class TestConfig {

        @Bean
        @Primary
        public SystemTypeDetector mockSystemTypeDetector() {
            SystemTypeDetector std = mock(SystemTypeDetector.class);
            when(std.getSystemType()).thenReturn(TYPE_C);
            return std;
        }

    }

    @Autowired
    private SystemTypeDetector systemTypeDetector;

    @Test
    void contextLoads() {
        assertThat(systemTypeDetector.getSystemType()).isEqualTo(TYPE_C);
    }
}

因为@TestConfiguration类是一个静态的内部类,所以只有通过这个测试才会自动选择它。必须将要放入@Before中的完整模拟行为移到初始化bean的方法中。

票数 47
EN

Stack Overflow用户

发布于 2021-05-20 11:30:15

我就这样修好了

代码语言:javascript
运行
复制
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyWebApplication.class, webEnvironment = RANDOM_PORT)
public class IntegrationTestNrOne {
    // this inner class must be static!
    @TestConfiguration
    public static class EarlyConfiguration {
       @MockBean 
       private SystemTypeDetector systemTypeDetectorMock;

       @PostConstruct 
       public void initMock(){
          Mockito.when(systemTypeDetectorMock.getSystemType()).thenReturn(TYPE_C);
       }
    }

    // here we can inject the bean created by EarlyConfiguration
    @Autowired 
    private SystemTypeDetector systemTypeDetectorMock;

    @Autowired
    private SomeOtherComponent someOtherComponent;

    @Test 
    public void testNrOne(){
       someOtherComponent.doStuff();
    }
}
票数 9
EN

Stack Overflow用户

发布于 2020-09-09 14:02:18

您可以使用以下技巧:

代码语言:javascript
运行
复制
@Configuration
public class Config {

    @Bean
    public BeanA beanA() {
        return new BeanA();
    }

    @Bean
    public BeanB beanB() {
        return new BeanB(beanA());
    }
}

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {TestConfig.class, Config.class})
public class ConfigTest {

    @Configuration
    static class TestConfig {

        @MockBean
        BeanA beanA;

        @PostConstruct
        void setUp() {
            when(beanA.someMethod()).thenReturn(...);
        }
    }
}

至少它适用于spring-boot-2.1.9.RELEASE

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40563409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档