单元测试 Spring ApplicationEvents - 事件正在发布,但侦听器没有触发?
我正在尝试对我在 Spring 中创建的自定义事件进行单元测试,但遇到了一个有趣的问题。如果我创建一个StaticApplicationContext
并手动注册和连接bean,我可以触发事件并查看从发布者(实现ApplicationEventPublisherAware
)到监听器(实现>ApplicationListener
)。
然而,当我尝试创建 JUnit 测试来使用 SpringJunit4ClassRunner 和 @ContextConfiguration 创建上下文时,一切正常,除了 ApplicationEvents 没有显示在侦听器中(我有确认它们正在发布)。
是否有其他方法来创建上下文以便 ApplicationEvents 能够正常工作?我在网上没有找到太多关于 Spring 事件框架单元测试的信息。
I'm trying to unit test the custom events that I've created in Spring and am running into an interesting problem. If I create a StaticApplicationContext
and manually register and wire the beans I can trigger events and see the program flow through the publisher (implements ApplicationEventPublisherAware
) through to the listener (implements ApplicationListener<?>
).
Yet when I try to create a JUnit test to create the context using the SpringJunit4ClassRunner
and @ContextConfiguration
everything works well except that the ApplicationEvents are not showing up in the listener (I have confirmed that they are getting published).
Is there some other way to create the context so that ApplicationEvents will work correctly? I haven't found much on the web about unit testing the Spring events framework.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这些事件不会触发,因为您的测试类没有从 Spring 应用程序上下文(即事件发布者)注册和解析。
我已经为此实现了一种解决方法,其中事件在另一个类中处理,该类作为 bean 向 Spring 注册并作为测试的一部分进行解析。这并不漂亮,但在浪费了一天中最好的时间试图找到更好的解决方案之后,我现在对此感到满意。
我的用例是当 RabbitMQ 消费者收到消息时触发一个事件。它由以下部分组成:
包装类
注意从测试中调用的 Init() 函数,该函数在从容器内解析后传入回调函数。 test
回调接口
测试配置类,用于定义单元测试中引用的bean。在此之前,需要从 applicationContext 解析并初始化它(请参阅下一步)。
最后,单元测试本身从 applicationContext 解析 bean 并调用 Init() 函数来传递断言标准(这假设您已将 bean 注册为单例 - Spring applicationContext 的默认值)。回调函数在此处定义,并传递给 Init()。
The events will not fire because your test classes are not registered and resolved from the spring application context, which is the event publisher.
I've implemented a workaround for this where the event is handled in another class that is registered with Spring as a bean and resolved as part of the test. It isn't pretty, but after wasting the best part of a day trying to find a better solution I am happy with this for now.
My use case was firing an event when a message is received within a RabbitMQ consumer. It is made up of the following:
The wrapper class
Note the Init() function that is called from the test to pass in the callback function after resolving from the container within the test
The callback interface
A test configuration class to define the bean which is referenced in the unit test. Before this is useful, it will need to be resolved from the applicationContext and initialsed (see next step)
Finally, the unit test itself that resolves the bean from the applicationContext and calls the Init() function to pass assertion criteria (this assumes you have registered the bean as a singleton - the default for the Spring applicationContext). The callback function is defined here and also passed to Init().
我只是将我的应用程序作为 SpringBootTest 运行,应用程序事件工作正常:
使用 @Captor / ArgumentCaptor 来验证事件的内容。
I just run my app as SpringBootTest, application events working fine:
use the @Captor / ArgumentCaptor to verify the content of your event.
您可以手动创建上下文。
例如:我需要检查我的
ApplicationListener
是否关闭了 Cassandra 连接:You can create a context manually.
For example: I had needed to check if my
ApplicationListener<ContextClosedEvent>
closed Cassandra connections: