這是我能想到的最小的獨立示例。
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
- 我幾乎從來沒有這樣做,因爲當我不希望我的測試使用AWS Queues和其他外部IO通道時,我經常會使用@Profile
來實現一些配置/ bean的不同實現。