Аннотированный метод @TransactionalEventListener не вызывается в тесте @Transactional - PullRequest
0 голосов
/ 15 февраля 2019

Я пытаюсь реализовать публикацию событий домена от сущности, следуя примерам, упомянутым в посте ниже:

Пример для @DomainEvents и @ AfterDomainEventsPublication

Однако мне не удалось заставить Spring вызывать мой метод с аннотацией @ TransactionalEventListener.

См. Ниже сущность, сервис, прослушиватель событий и тестовый код:

@Entity
public class Book extends AbstractAggregateRoot<Book>
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(unique = true)
    private String isbn;

    @Column
    private String name;

    public Book(String isbn, String name)
    {
        this.isbn = isbn;
        this.name = name;
    }

    public void purchase()
    {
        registerEvent(new BookPurchasedEvent(id));
    }

    // getters omitted for brevity
}

Сервис:

@Service
@Transactional
public class BookService
{
    private final BookRepository bookRepository;

    public BookService(BookRepository bookRepository)
    {
        this.bookRepository = bookRepository;
    }

    public void purchaseBook(Integer bookId)
    {
        Book book = bookRepository.findById(bookId)
                                .orElseThrow(NoSuchElementException::new);

        book.purchase();

        bookRepository.save(book);
    }
}

Слушатель:

@Service
public class EventListener
{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @TransactionalEventListener
    public void handleEvent(BookPurchasedEvent event)
    {
        logger.info("Received event {}", event);
    }
}

Тест:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class BookEventsTest
{
    @Autowired
    private BookService bookService;

    @Autowired
    private EntityManager entityManager;

    @Test
    public void test()
    {
        Book book = new Book("abcd-efgh", "El Quijote");
        book = entityManager.merge(book);

        bookService.purchaseBook(book.getId());
    }
}

Сообщение журнала от слушателя не регистрируется.Хотя он работает как REST-сервис и вызывается, например, через Postman

1 Ответ

0 голосов
/ 18 февраля 2019

Понял.Поскольку мой тест помечен @Transactional, транзакция, заключающая в себе метод теста, будет откатана.Поэтому метод, аннотированный @TransactionalEventListener, вызываться не будет, поскольку по умолчанию он запускается на этапе TransactionPhase.AFTER_COMMIT (и я не заинтересован в том, чтобы его вызывали, если транзакция не была успешной).Так что рабочая версия теста выглядит следующим образом:

@RunWith(SpringRunner.class)
@SpringBootTest
public class BookEventsTest
{
    @Autowired
    private BookService bookService;

    @Autowired
    private BookRepository bookRepository;

    @MockBean
    private EventListener eventListener;

    private Book book;

    @Before
    public void init() {
        book = bookRepository.save(new Book("abcd-efgh", "El Quijote"));
    }

    @After
    public void clean() {
        bookRepository.deleteAll();
    }

    @Test
    public void testService()
    {
        bookService.purchaseBook(book.getId());

        then(eventListener)
                .should()
                .handleEvent(any(BookPurchasedEvent.class));
    }
}
...