本文介绍了在应用程序启动之前配置@MockBean组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring Boot 1.4.2应用程序.在启动过程中使用的一些代码如下所示:

I have a Spring Boot 1.4.2 application. Some code which is used during startup looks like this:

@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: ...
        }
    }
}

有一个确定系统类型的组件.在从其他组件启动期间使用此组件.在生产中一切正常.

There is a component which determines the system type. This component is used during startup from other components. In production everything works fine.

现在,我想使用Spring 1.4的@MockBean添加一些集成测试.

Now I want to add some integration tests using Spring 1.4's @MockBean.

测试如下:

@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,则会返回.

Basically the mocking works fine. My systemTypeDetectorMock is used and if I call getSystemType -> TYPE_C is returned.

问题是该应用程序无法启动.目前,春天的工作秩序似乎是:

The problem is that the application doesn't start. Currently springs working order seems to be:

  1. 创建所有Mocks(无需配置,所有方法均返回null)
  2. 启动应用程序
  3. 调用@Before方法(将在其中配置模拟)
  4. 开始测试

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

My problem is that the application starts with an uninitialized mock. So the call to getSystemType() returns null.

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

My question is: How can I configure the mocks before application startup?

编辑:如果有人遇到相同的问题,则一种解决方法是使用@MockBean(answer = CALLS_REAL_METHODS).这调用了真正的组件,在我的情况下,系统启动了.启动后,我可以更改模拟行为.

If somebody has the same problem, one workaround is to use @MockBean(answer = CALLS_REAL_METHODS). This calls the real component and in my case the system starts up. After startup I can change the mock behavior.

推荐答案

在这种情况下,您需要采用引入@MockBean之前所用的方式配置模拟-通过手动指定一个@Primary bean在上下文中替换原始的.

In this case you need to configure mocks in a way we used to do it before @MockBean was introduced - by specifying manually a @Primary bean that will replace the original one in the context.

@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的方法.

Since @TestConfiguration class is a static inner class it will be picked automatically only by this test. Complete mock behaviour that you would put into @Before has to be moved to method that initialises a bean.

这篇关于在应用程序启动之前配置@MockBean组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 19:09