如何测试Spring @EventListener方法?

JiK*_*Kra 4 spring unit-testing

我有一些事件发布:

@Autowired private final ApplicationEventPublisher publisher;
...
publisher.publishEvent(new MyApplicationEvent(mySource));
Run Code Online (Sandbox Code Playgroud)

我有这个事件监听器:

class MyApplicationEventHandler {

    @Autowired SomeDependency someDependency;

    @EventListener public void processEvent(final MyApplicationEvent event) {
        // handle event...
    }
}
Run Code Online (Sandbox Code Playgroud)

我需要使用EasyMock进行测试。有没有一种简单的方法可以在测试中发布某些内容并断言我的事件侦听器做了什么?

编辑:

我试图创建这样的模拟测试:

// testing class
SomeDependency someDependency = mock(SomeDependency.class);

MyApplicationEventHandler tested = new MyApplicationEventHandler(someDependency);

@Autowired private final ApplicationEventPublisher publisher;

@Test
public void test() {
    someDependency.doSomething(anyObject(SomeClass.class));
    replay();
    publisher.publishEvent(new MyApplicationEvent(createMySource()));
}
Run Code Online (Sandbox Code Playgroud)

没用

java.lang.AssertionError: 
  Expectation failure on verify:
    SomeDependency.doSomething(<any>): expected: 1, actual: 0
Run Code Online (Sandbox Code Playgroud)

And*_*eas 8

如果无法启动整个 Spring 上下文,ApplicationContextRunner则引入了 Spring Boot 2.0.0 。

ApplicationContextRunner 可以在您的测试中创建应用程序上下文,从而可以更好地控制上下文。

一个完整的测试示例可能是:

package net.andreaskluth.context.sample;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

public class SimpleEventTest {

  private final ApplicationContextRunner runner = new ApplicationContextRunner();

  @Test
  public void happyPathSuccess() {
    AtomicBoolean sideEffectCausedByEvent = new AtomicBoolean(false);
    ObservableEffect effect = () -> sideEffectCausedByEvent.set(true);

    runner
        .withBean(SomeEventListener.class, effect)
        .run(
            context -> {
              context.publishEvent(new SomeEvent());
              assertThat(sideEffectCausedByEvent.get()).isTrue();
            });
  }

  public interface ObservableEffect {
    void effect();
  }

  @Component
  public static class SomeEventListener {

    private final ObservableEffect effect;

    public SomeEventListener(ObservableEffect effect) {
      this.effect = effect;
    }

    @EventListener(SomeEvent.class)
    public void listen() {
      effect.effect();
    }
  }

  public static class SomeEvent {}
}

Run Code Online (Sandbox Code Playgroud)


lan*_*ell 7

首先,当您使用Spring Boot时,对它们的测试变得非常简单。此测试将启动引导上下文并注入ApplicationEventPublisher的真实实例,但创建模拟的SomeDependency实例。该测试将发布所需的事件,并验证您的模拟是否按预期被调用。

@RunWith(SpringRunner.class)
@SpringBootTest
public class EventPublisherTest {

   @Autowired 
   private final ApplicationEventPublisher publisher;

   @MockBean
   private SomeDependency someDependency;

   @Test
   public void test() {
      publisher.publishEvent(new MyApplicationEvent(createMySource()));

      // verify that your method in you 
      verify(someDependency, times(1)).someMethod();
   }
}
Run Code Online (Sandbox Code Playgroud)