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

新手上路,请多包涵

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

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

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

现在我想使用 Spring 1.4 的 @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 返回。

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

  1. 创建所有模拟(没有配置所有方法返回 null)
  2. 开始申请
  3. 调用@Before-methods(配置模拟的地方)
  4. 开始测试

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

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

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

原文由 Marcel 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 466
1 个回答

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

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

原文由 Maciej Walkowiak 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题