如何使用Spring,JUnit和Mockito验证事件是否已发布?

时间:2017-06-28 17:12:12

标签: spring events junit mockito spring-4

我正在使用Spring 4.3.8.RELEASE和JUnit 4.12以及Mockito 1.10.18。我有一个发布活动的服务......

@Service("organizationService")
@Transactional
public class OrganizationServiceImpl implements OrganizationService, ApplicationEventPublisherAware

            publisher.publishEvent(new ZincOrganizationEvent(id));

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) 
    {
        this.publisher = publisher;
    }

    ...
    @Override
    public void save(Organization organization)
    {
    ...
    publisher.publishEvent(new ThirdPartyEvent(organization.getId()));

我的问题是,如何在JUnit测试中验证事件是否已实际发布?

@Test
public void testUpdate()
{

m_orgSvc.save(org);
// Want to verify event publishing here

2 个答案:

答案 0 :(得分:0)

如果您想测试是否忘记在publishEvent内拨打OrganizationServiceImpl方法,可以使用以下内容:

class OrganizationServiceImplTest {

    private OrganizationServiceImpl organizationService;

    private ApplicationEventPublisher eventPublisher;

    @Before
    public void setUp() {
        eventPublisher = mock(ApplicationEventPublisher.class);

        organizationService = new OrganizationServiceImpl();
        organizationService.setApplicationEventPublisher(eventPublisher)
    }

    @Test
    public void testSave() {

        /* ... */

        organizationService.save(organization);

        verify(eventPublisher).publishEvent(any(ThirdPartyEvent.class));
    }

}

上面的测试用例将验证是否存在publishEvent方法的调用。

了解更多check the documentation

关于:

  

我的问题是,如何在JUnit测试中验证事件是否已实际发布?

如果要验证实际发送,则必须测试ApplicationEventPublisher实施,并且可能没有模拟。

答案 1 :(得分:0)

我更喜欢相反的方法,那就是 integration test-ey

  • ‍♂️使用Mockito模拟ApplicationListener
  • 将模拟应用程序侦听器注册到ConfigurableApplicationContext
  • 工作
  • ✔验证模拟对象已收到事件

使用这种方法,您正在测试某人已经收到某个事件,这已经发布了一个事件。

这是基本身份验证测试的代码。在其他情况下,我测试是否发生了登录事件

@Test
public void testX509Authentication() throws Exception
{
    ApplicationListener<UserLoginEvent> loginListener = mock(ApplicationListener.class);
    configurableApplicationContext.addApplicationListener(loginListener);

    getMockMvc().perform(get("/").with(x509(getDemoCrt())))//
                .andExpect(status().is3xxRedirection())//
                .andExpect(redirectedUrlPattern("/secure/**"));

    getErrorCollector().checkSucceeds(() -> {
        verify(loginListener, atLeastOnce()).onApplicationEvent(any(UserLoginEvent.class));
        return null;
    });
}

我的建议是释放Mockito的功能以深入验证事件参数。就我而言,我将代码扩展到:

  • 检查登录事件中的用户名是否与已验证的主体匹配
  • 在用户公然无法登录的情况下执行其他测试,我将期望各种登录失败事件之一