当前位置: 首页 > 知识库问答 >
问题:

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

容阳焱
2023-03-14

我有一个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: ...
        }
    }
}

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

现在,我想使用Spring1.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-

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

  1. 创建所有模拟(无配置,所有方法返回null)
  2. 启动应用程序
  3. 调用@Before方法(在此处配置模拟)
  4. 启动测试

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

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

编辑:如果有人有同样的问题,一个解决方法是使用@MockBean(answer=CALLS\u REAL\u METHODS)。这将调用真正的组件,在我的情况下,系统将启动。启动后,我可以更改模拟行为。

共有3个答案

广晔
2023-03-14

您可以使用以下技巧:

@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。发布

晏弘雅
2023-03-14

我能这样修好它

@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();
    }
}
龚同
2023-03-14

在这种情况下,您需要以引入MockBean之前的方式配置Mock,即手动指定一个将在上下文中替换原始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类是一个静态的内部类,因此只有通过此测试才能自动选择它。您将在之前放入的完整模拟行为必须移动到初始化bean的方法。

 类似资料:
  • 我们的webstart应用程序(不是小程序)遇到了奇怪的启动问题。 启动应用程序会显示应用程序启动屏幕,但javaws进程会在不久后终止,不会在对话框、java控制台或日志文件中显示任何错误消息。javaws似乎只是在实际启动实际应用程序之前停止。无论用户尝试从桌面快捷方式还是从网页启动应用程序,都无关紧要。当从本地计算机使用javaw运行而无需webstart时,相同的应用程序可以正常工作。 应

  • 14:10:16.944[reactor-http-nio-1]调试org.springframework.http.codec.json.jackson2jsondecoder-[4EF27D66]解码[响应(data=hello)] 14:10:16.944[reactor-http-nio-1]调试reactor.netty.resources.pooledconnectionprovide

  • 我正在使用Angular2RC5。我希望能够在我的应用程序启动之前加载我的服务器IP地址和一些其他配置参数。我如何在最新的RC5中做到这一点? 我看过其他文章,但没有帮助: 如何在angular2中预加载配置文件:这里提供的答案是特定于webpad的。我正在使用系统js。 https://medium.com/@hasan.hameed/reading-configuration-files-in

  • 我正在尝试在web应用程序中使用Freemarker进行电子邮件模板制作。 我声明了一个FreeMarkerConfiguration FactoryBean,如下所示: 运行我的JUnit时一切正常,但在我的webapp中运行时,我的bean被Spring启动FreeMarkerAutoConfiguration“覆盖”。 我已尝试: 从我的gradle文件中删除sping-boot-start

  • 使用以下命令启动Appium服务器:C:\Program Files(x86)\Appium\node.exelib\server\main.js-地址127.0.0.1-端口4723-平台名称Android-平台-版本23-自动化-名称Appium-日志-无颜色info:欢迎来到Appium v1.4.16(REV ae6877eff263066b26328d457bd285c0cc62430d

  • 问题内容: 据我所知,您只能使用VisualVM来分析正在运行的应用程序。 有谁知道使用VisualVM剖析Java应用程序启动和启动的方法吗? 我相信必须有一种方法,否则将是一个重大的疏忽。 希望我只是误读了文档。 谢谢,第 问题答案: 您是否要使用`-Xrunjdwp“命令行选项来设置性能分析?如果是,则该选项仅出于此目的具有” suspend“参数 : 如果要在加载主类之前立即挂起目标VM,