Spring Boot单元测试中,如何在不启动整个应用程序的情况下使@Autowired生效

huangapple go评论70阅读模式
英文:

Spring Boot Unit Test with @Autowired how to get it to to work without starting entire Application

问题

我正在尝试对使用@Configuration注释的类的配置进行单元测试。该类相当简单:

@Configuration
@ConfigurationProperties(prefix = "feed")
public class SpringNyseFeedConfig extends FeedConfig {
    private static final Logger LOG = LoggerFactory.getLogger(SpringNyseFeedConfig.class);	

    public SpringNyseFeedConfig() {
        LOG.debug("ctor():created {}", SpringNyseFeedConfig.class);
    }
    
    @PostConstruct
    public void completeConfig() {
        LOG.debug("completeConfig(): validating configuration...");
        postConfigure().validate();  // 需要设置最终属性并验证
    }
}

这个单元测试也很简单:

@SpringBootTest
@ActiveProfiles("test")
public class SpringNyseFeedConfigTest {

    @Autowired
    private SpringNyseFeedConfig config;
    
    @Test
    void propertiesReadAsExpected() {
        assertNotNull(config);
        ServerConnection requestServer = config.getRequestServer();
        assertEquals("192.168.1.200", requestServer.getHost());
        // ...
        // ...
    }

}

测试可以正确地注入config,并配置了从application-test.yml文件中读取的属性。

问题在于这个测试会导致Spring初始化应用程序中的所有Bean(这需要时间)。

我尝试了大约半打建议,试图限制测试仅实例化SpringNyseFeedConfig对象,但它们都导致要么根本不注入任何东西(config等于null),要么注入一个未从yml文件配置的对象(即未设置属性)。

我该如何更新单元测试,以便它将读取文件并自动配置和注入SpringNyseFeedConfig对象,而无需实例化应用程序中的每个其他组件?

英文:

I am trying to unit test configuration of a class annotated with @Configuration. The class is fairly simple:

@Configuration
@ConfigurationProperties(prefix = "feed")
public class SpringNyseFeedConfig extends FeedConfig {
	private static final Logger LOG = LoggerFactory.getLogger(SpringNyseFeedConfig.class);	

	public SpringNyseFeedConfig() {
		LOG.debug("ctor():created {}", SpringNyseFeedConfig.class);
	}
	
	@PostConstruct
	public void completeConfig() {
		LOG.debug("completeConfig(): validating configuration...");
		postConfigure().validate();  // need to set final properties and validate
	}
}

The unit test is also simple:

@SpringBootTest
@ActiveProfiles("test")
public class SpringNyseFeedConfigTest {

	@Autowired
	private SpringNyseFeedConfig config;
	
	@Test
	void propertiesReadAsExpected() {
		assertNotNull(config);
		ServerConnection requestServer = config.getRequestServer();
		assertEquals("192.168.1.200", requestServer.getHost());
        ...
        ...    		
	}

}

The test is getting the config injected correctly, and configured with properties read from an application-test.yml file.

The problem is that the test causes Spring initializes all the Beans in the application (which is time consuming).

I've tried about a half dozen suggestions to try to limit the test to only instantiating the SpringNyseFeedConfig object only, but they have all resulted in either not injecting anything at all (config == null), or injecting an object not configured from the yml file (i.e. no properties set).

How can I update the unit test so that it will read the file and auto-configure and inject the SpringNyseFeedConfig object without instantiating every other component in the application?

答案1

得分: 1

有一个专用的注解 `@TestPropertySource` 用于启用对 `ConfigurationProperties` 的测试这应该按预期工作

```java
@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties(value = SpringNyseFeedConfig .class)
@TestPropertySource("/application-test.properties")
public class SpringNyseFeedConfigTest {

    @Autowired
    private SpringNyseFeedConfig config;
// ...
}

请注意:我故意使用属性而不是YAML文件,因为后者在测试中不能正常工作。

基于:https://www.baeldung.com/spring-boot-testing-configurationproperties


<details>
<summary>英文:</summary>

There is a dedicated annotation `@TestPropertySource` to enable testing of `ConfigurationProperties`. This should work as expected:

@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties(value = SpringNyseFeedConfig .class)
@TestPropertySource("/application-test.properties")
public class SpringNyseFeedConfigTest {

@Autowired
private SpringNyseFeedConfig config;

// ...
}

Please note: I&#39;m intentionally using properties instead YAML file because the latter doesn&#39;t work properly with tests.

Based on: [https://www.baeldung.com/spring-boot-testing-configurationproperties][1]


  [1]: https://www.baeldung.com/spring-boot-testing-configurationproperties

</details>



# 答案2
**得分**: 1

使用`ApplicationRunner`来组装上下文。

```kotlin
// kotlin 代码片段
class YourTests{

    private val contextRunner = ApplicationContextRunner()

    @Test
    fun testAppProperties() {
        contextRunner
            .withUserConfiguration(YourConfig::class.java)
            .run {
                val bean: YourBean = it.getBean(YourBean::class.java)
                assertThat(bean.baseUrl).isEqualTo("http://localhost:8080")
            }
    }
}

Java 版本:

public class YourTests{

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();

    @Test
    public void testAppProperties() {
        contextRunner
            .withUserConfiguration(YourConfig.class)
            .run( ctx -> {
                var bean = ctx.getBean(YourBean.class);
                assertThat(bean.baseUrl).isEqualTo("http://localhost:8080");
           });
    }
}
英文:

Use ApplicationRunner to assemble the context.

// kotlin code fragment
class YourTests{

    private val contextRunner = ApplicationContextRunner()

    @Test
    fun testAppProperties() {
        contextRunner
            .withUserConfiguration(YourConfig::class.java)
            .run {
                val bean: YourBean = it.getBean(YourBean::class.java)
                assertThat(bean.baseUrl).isEqualTo(&quot;http://localhost:8080&quot;)

            }
    }
}

Java version:

public class YourTests{

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();

    @Test
    public void testAppProperties() {
        contextRunner
            .withUserConfiguration(YourConfig.class)
            .run( ctx -&gt; {
                var bean = ctx.getBean(YourBean.class);
                assertThat(bean.baseUrl).isEqualTo(&quot;http://localhost:8080&quot;);

           });
    }
}

huangapple
  • 本文由 发表于 2023年6月22日 06:08:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76527454.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定