java - 测试Spring onApplicationEvent的简单方法

标签 java spring unit-testing junit event-listener

我有一个包含函数的应用程序事件监听器:

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
//do some stuff
}

我如何编写单元测试来模拟 ContextRefreshedEvent,就像我的 jar 被执行一样,并测试我的 onApplicationEvent 函数是否完成了它应该做的事情?

最佳答案

这是我能想到的最小的独立示例。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.concurrent.LinkedBlockingQueue;

import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RefreshTest.MyConfig.class})
public class RefreshTest {

    @Autowired
    private MyListener listener;

    @Test
    public void test() {
        assertEquals("Refresh should be called once",1, listener.events.size());
    }

    public static class MyConfig {
        @Bean
        public MyListener listener() {
            return new MyListener();
        }
    }

    public static class MyListener implements ApplicationListener <ContextRefreshedEvent> {
        // you don't really need a threadsafe collection in a test, as the test main thread is also loading the spring contest and calling the handler, 
        // but if you are inside an application, you should be aware of which thread is calling in case you want to read the result from another thread. 
        LinkedBlockingQueue<ContextRefreshedEvent> events = new LinkedBlockingQueue<ContextRefreshedEvent>();
        public void onApplicationEvent(ContextRefreshedEvent  event) {
            events.add(event);
        }
    }
}

测试处理程序内部的代码与调用处理程序之间存在差异。不要将代码直接放在处理程序中,而是放在另一个从处理程序调用的 bean 中,这样您就可以在没有处理程序的情况下测试逻辑(通过使用您创建的 ContextRefreshedEvent 调用它)。刷新上下文时(通常是加载时)会发送刷新事件,因此无需对其进行测试。如果它没有在您的生产代码中被调用,您通常会立即注意到。此外,测试和生产之间的上下文加载可能不同,因此即使您编写的测试显示调用了处理程序,也不能保证它会在生产中调用,除非您使用完全相同的 @Configuration 运行- 我几乎从不这样做,因为我经常最终使用 @Profile 对某些配置/bean 进行不同的实现,例如当我不希望我的测试使用 AWS 队列时,并且其他外部 IO channel 。

关于java - 测试Spring onApplicationEvent的简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43527334/

相关文章:

spring - 在 Spring 中使用 Velocity Webapp ResourceLoader

.net - MSTest 是否有流畅的断言 API?

c# - 解析 HTML 片段

java - 将代码从 java 转换为 python

java - 将不同的 Grizzly HttpHandler 绑定(bind)到不同的 NetworkListener

java - Thymeleaf 上下文 URL 处理 - 如何将语言代码添加到上下文相关 URL (Spring + Thymeleaf)

javascript - 如何为 jquery 调用 `$(some)` 创建 spy ?

java - 试图抽象一些东西,我是否试图过度简化?

java - 检查用户是否订阅的正确方法?

java - JPA - 复合 key 识别中的关系