我目前正在一个使用WebSocket的Spring Boot项目中为我的控制器编写测试。由于很难获得有关该主题的信息,我唯一的线索是文档推荐的这个示例。请允许我尝试解释到目前为止我的尝试,尝试理解并设置我的测试环境。我遵循的是基于上下文的方法,我在@WebMvcTest
和@ContextConfiguration
(示例使用)之间左右为难。我使用@WebMvcTest
的动机是Spring Boot文档中的这句话:
在测试Spring Boot应用程序时,通常不需要使用此[使用@ContextCon人和(类=…)
来指定要加载的Spring@Con人和
,或者在测试中使用嵌套的@配置
类]。Spring Boot的@*测试
注释会在您没有明确定义时自动搜索您的主要配置。
因此,@WebMvcTest
似乎特别适合该任务,因为它只关注web层,只将扫描的bean集限制为那些必需的bean(例如@controller
),而不是旋转一个完整的ApplicationContext
。
下面的代码示例使用字段注入来初始化通道拦截器,以捕获通过它们发送的消息。
@Autowired private AbstractSubscribableChannel clientInboundChannel;
@Autowired private AbstractSubscribableChannel clientOutboundChannel;
@Autowired private AbstractSubscribableChannel brokerChannel;
据我所知,这些字段使得示例中的< code>TestConfig类(完整的类定义见最后的代码块)的存在成为必要,因为如果没有它,我会得到一个错误,说没有beans符合autowire候选的条件。我相信< code>TestConfig中的这两个字段是关键:
@Autowired
private List<SubscribableChannel> channels;
@Autowired
private List<MessageHandler> handlers;
但是,如果没有< code > @ context configuration(classes =[WebSocketConfig::class])(< code > WebSocketConfig 是我自己的WebSocket配置文件),这两个字段总是< code>null导致错误。到目前为止,这意味着需要< code > @ context configuration(classes =[WebSocketConfig::class])与< code>TestConfig的组合。
有趣的是,如果没有< code > @ WebMvcTest ,< code > clientInboundChannel 、< code > clientOutboundChannel 和< code>brokerChannel实际上永远不会初始化。因此,留给我的是,我既需要< code>@WebMvcTest又需要< code > @ context configuration ,这似乎有点奇怪。示例回购的最后一次更新已经超过两年了,我无法摆脱这种感觉,即它可能有些过时了。
这就是我的测试类(静态编程语言)当前的样子。为了简洁起见,我省略了createroom
测试用例:
@WebMvcTest(controllers = [RoomController::class])
@ContextConfiguration(classes = [WebSocketConfig::class, RoomControllerTests.TestConfig::class])
class RoomControllerTests {
@Autowired
private lateinit var clientInboundChannel: AbstractSubscribableChannel
@Autowired
private lateinit var clientOutboundChannel: AbstractSubscribableChannel
@Autowired
private lateinit var brokerChannel: AbstractSubscribableChannel
private lateinit var clientOutboundChannelInterceptor: TestChannelInterceptor
private lateinit var brokerChannelInterceptor: TestChannelInterceptor
private lateinit var sessionId: String
@BeforeEach
fun setUp() {
brokerChannelInterceptor = TestChannelInterceptor()
clientOutboundChannelInterceptor = TestChannelInterceptor()
brokerChannel.addInterceptor(brokerChannelInterceptor)
clientOutboundChannel.addInterceptor(clientOutboundChannelInterceptor)
}
@Test
fun createRoom() {
// test room creation
// ...
}
@Configuration
internal class TestConfig : ApplicationListener<ContextRefreshedEvent?> {
@Autowired
private val channels: List<SubscribableChannel>? = null
@Autowired
private val handlers: List<MessageHandler>? = null
override fun onApplicationEvent(event: ContextRefreshedEvent) {
for (handler in handlers!!) {
if (handler is SimpAnnotationMethodMessageHandler) {
continue
}
for (channel in channels!!) {
channel.unsubscribe(handler)
}
}
}
}
}
这里发布的答案是我开始了解如何使用@WebMvcTest
和@ContextConfiguration
的第一个线索。看起来真正必要的行是@ContextConfiguration(classes = [WebSocketConfig::class]),
因为没有它,就找不到必要的配置(在这种情况下是我自己的WebSocketConfig
)。
虽然< code>@WebMvcTest(以及一般的测试切片)确实会自动搜索主要配置,但是由主应用程序类定义的配置是找到的配置,因为该类是用< code > @ spring boot application 注释的。
更重要的是,像@WebMvctest
这样的测试切片完全排除了扫描中的@配置
类,这意味着它们不会包含在测试切片加载的应用程序上下文中。支持这一点的事实是,如果@WebMvctest
被替换为@SpringBoottest
-即使没有@ContextConfiation(类=[WebSocketConfig::class])
-这意味着WebSocketConfig
已加载。
总而言之,在我看来,有三种方法可以将非主要配置包含在应用程序上下文中,以便在集成测试中检测到它:
@SpringBoottest
注释测试类(并且可选地@ContextConfigation
以将加载的bean数量限制为仅需要的数量)@WebMvctest
)结合@ContextConfigation
@WebMvctest
)并在主类中定义配置(即用@SpringBootApplication
注释的类)