首页 > 解决方案 > 使用 @RestClientTest 排除 @SpringBootApplication 类进行单元测试

问题描述

我有一个简单的服务类,它使用RestTemplate. 我正在测试它@RestClientTest并期望只初始化所需的服务 bean

@SpringBootApplication
class DemoApplication {
    @Bean fun restTemplate() = RestTemplateBuilder().build()

    @Bean fun xyzService() = XyzService()
}

@Service
class MyServiceImpl(private val restTemplate: RestTemplate): MyService {
    override fun fetch(id: String) {
        print(restTemplate.getForObject(URI("http://localhost:9090"), String::class.java))
    }
}

@RestClientTest(MyServiceImpl::class)
@AutoConfigureWebClient(registerRestTemplate = true)
class MyServiceTest {
    @Autowired
    private lateinit var mockServer: MockRestServiceServer
    @Autowired
    private lateinit var myService: MyService

    @Test
    fun test(){
        mockServer.expect(ExpectedCount.once(), MockRestRequestMatchers.requestTo(URI("http://localhost:9090")))
            .andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
            .andRespond(MockRestResponseCreators.withStatus(HttpStatus.OK)
                .contentType(MediaType.APPLICATION_JSON)
                .body("hello world"))

        myService.fetch("123")

    }
}

我想排除DemoApplication在测试中被初始化的,只有要测试的服务类的bean。问题是bean初始化xyzService失败(它依赖于RabbitTemplate),我不想用模拟弄乱测试代码。

标签: spring-bootunit-testingkotlinspring-testjunit5

解决方案


@RestClientTest 将无法正确过滤掉在 @SpringBootApplication-class 中定义的组件(对于在主类上定义的 @EnableJpaRepositories 等配置注释也是如此)。将您的 bean 移动到使用 @Configuration 注释的其他类:

@SpringBootApplication
class DemoApplication { }

@Configuration
class BeansConfig{
    @Bean fun restTemplate() = RestTemplateBuilder().build()

    @Bean fun xyzService() = XyzService()
}

根据 Spring-Boot 的文档:

如果您使用测试注释来测试应用程序的更具体部分,则应避免在主方法的应用程序类上添加特定于特定区域的配置设置。

@SpringBootApplication 的底层组件扫描配置定义了排除过滤器,用于确保切片按预期工作。如果您在 @SpringBootApplication-annotated 类上使用显式 @ComponentScan 指令,请注意这些过滤器将被禁用。如果您使用切片,则应重新定义它们。


推荐阅读