How to test Spring @EventListener method?

前端 未结 3 827
遇见更好的自我
遇见更好的自我 2021-01-11 23:04

I have some event publishing:

@Autowired private final ApplicationEventPublisher publisher;
...
publisher.publishEvent(new MyApplicationEvent(mySource));


        
相关标签:
3条回答
  • 2021-01-11 23:38

    In case, spinning up the whole Spring context is not an option, with Spring Boot 2.0.0 ApplicationContextRunner was introduced.

    ApplicationContextRunner can create an application context in your test, allowing for more control over the context.

    A complete test example could be:

    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 {}
    }
    
    
    0 讨论(0)
  • 2021-01-11 23:58

    First, As you're using Spring Boot, the testing of these becomes pretty straightforward. This test will spin up the boot context and inject a real instance of ApplicationEventPublisher, but create a mocked instance of SomeDependency. The test publishes the desired event, and verifies that your mock was invoked as you expected.

    @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();
       }
    }
    
    0 讨论(0)
  • 2021-01-11 23:58

    The option I took was to create a TestConfiguration and a listener within the test itself like this:

    @Slf4j
    @ExtendWith(SpringExtension.class)
    @SpringBootTest(classes = {RegistrationConfiguration.class, RegistrationTestConfiguration.class})
    class RegistrationServiceIntegrationTest {
    
        @Autowired
        private DynamoDBMapper dynamoDBMapper;
        @Autowired
        private AmazonDynamoDBAsync amazonDynamoDB;
        @Autowired
        private RegistrationRepository repository;
        @Autowired
        private ApplicationEventPublisher eventPublisher;
    
        private String personaId;
    
        private RegistrationService testObj = null;
    
        @BeforeEach void setup() {
            RegistrationServiceDBHelper.initializeTable(dynamoDBMapper, amazonDynamoDB, repository);
            personaId = UUID.randomUUID().toString();
            testObj = new RegistrationService(repository, eventPublisher);
        }
    
    
        @TestConfiguration
        static class RegistrationTestConfiguration {
            @Bean
            RegistrationServiceEventListener eventListener() {
                return new RegistrationServiceEventListener();
            }
        }
    
    
        @Component
        public static class RegistrationServiceEventListener {
            @TransactionalEventListener
            public void onPlayerRegisteredEvent(PlayerRegisteredEvent event) {
                log.info("Received new user event {}", event.personaId());
                assertThat(event.personaId()).isNotBlank();
            }
        }
    
    
        @DisplayName("given a persona id that is not registered")
        @Nested class WhenNoPlayerIsRegistered {
    
            @DisplayName("when a player is registered"
                    + " then an event is raised")
            @Test void raisePlayerRegisteredEvent() {
                // When
                testObj.registerPlayer(personaId);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题