Spring Boot - 单元测试ApplicationReadyEvent业务逻辑

时间:2016-06-27 10:36:29

标签: spring unit-testing spring-boot

我有一个简单的服务,我用默认用户预填充user db表。该服务如下所示:

@Service
public class BootstrapService
{
    @Autowired
    UserRepository userRepository;

    public void bootstrap()
    {
        User user = new User("admin", "password");
        userRepository.save(user);
    }
}

我在应用程序启动时使用ApplicationListener

调用此服务
@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent>
{
    @Autowired
    private BootstrapService bootstrapService;

    @Override
    public void onApplicationEvent(final ApplicationReadyEvent event)
    {
        bootstrapService.bootstrap();
    }
}

现在我想为BootstrapService编写一个单元测试来检查是否真的添加了用户,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@Transactional
public class BootstrapServiceTests
{
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BootstrapService bootstrapService;

    @Test
    public void testBootstrap()
    {
        bootstrapService.bootstrap();

        assertEquals(1, userRepository.count());
    }
}

然而,会发生的事情是bootstrapService.bootstrap()函数被调用两次 - 一次由ApplicationListener调用,一次由测试本身调用,导致两个用户被添加到数据库中。

如何在运行测试时阻止ApplicationListener#ApplicationReadyEvent被触发?

2 个答案:

答案 0 :(得分:2)

如评论中所述,您可以尝试模拟监听器(但我不确定它是否可以在这种精确的情况下工作)。我能想到的其他方式(这是肯定的)是使用Spring配置文件,以排除ApplicationStartup在测试配置文件中运行,如下所示:

@Component
@Profile("!test")
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent>

然后,当您运行测试时,只需使用环境开关:--spring.profiles.active=test

缺点是ApplicationStartup将在每次使用“test”配置文件的测试中排除。

答案 1 :(得分:0)

如果您使用的是@EventListener

@EventListener(
    value = ApplicationReadyEvent.class,
    condition = "@environment.getActiveProfiles()[0] != 'test'")
public void onStartup() throws IOException {}