Я пишу интеграционный тест, используя SpringJUnit4ClassRunner
. У меня есть базовый класс:Откат транзакции JUnit с методом @Async
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({ /*my XML files here*/})
@Ignore
public class BaseIntegrationWebappTestRunner {
@Autowired
protected WebApplicationContext wac;
@Autowired
protected MockServletContext servletContext;
@Autowired
protected MockHttpSession session;
@Autowired
protected MockHttpServletRequest request;
@Autowired
protected MockHttpServletResponse response;
@Autowired
protected ServletWebRequest webRequest;
@Autowired
private ResponseTypeFilter responseTypeFilter;
protected MockMvc mockMvc;
@BeforeClass
public static void setUpBeforeClass() {
}
@AfterClass
public static void tearDownAfterClass() {
}
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilter(responseTypeFilter).build();
}
@After
public void tearDown() {
this.mockMvc = null;
}
}
Тогда я продлить его и создать тест с использованием mockMvc:
public class MyTestIT extends BaseMCTIntegrationWebappTestRunner {
@Test
@Transactional("jpaTransactionManager")
public void test() throws Exception {
MvcResult result = mockMvc
.perform(
post("/myUrl")
.contentType(MediaType.APPLICATION_XML)
.characterEncoding("UTF-8")
.content("content")
.headers(getHeaders())
).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_XML))
.andExpect(content().encoding("ISO-8859-1"))
.andExpect(xpath("/*[local-name() ='myXPath']/")
.string("result"))
.andReturn();
}
В конце потока, объект сохраняется в БД. Но требование здесь состоит в том, что это должно выполняться асинхронно. Так считают этот метод называется:
@Component
public class AsyncWriter {
@Autowired
private HistoryWriter historyWriter;
@Async
public void saveHistoryAsync(final Context context) {
History history = historyWriter.saveHistory(context);
}
}
HistoryWriter
Тогда называется:
@Component
public class HistoryWriter {
@Autowired
private HistoryRepository historyRepository;
@Transactional("jpaTransactionManager")
public History saveHistory(final Context context) {
History history = null;
if (context != null) {
try {
history = historyRepository.saveAndFlush(getHistoryFromContext(context));
} catch (Throwable e) {
LOGGER.error(String.format("Cannot save history for context: [%s] ", context), e);
}
}
return history;
}
}
Проблема со всем этим в том, что после того, как тест будет сделано, History
объект остается в БД. Мне нужно сделать тестовую транзакцию для отмены всех изменений в конце.
Теперь, что я пытался до сих пор:
- Удалить
@Async
аннотацию. Очевидно, это не может быть решением, но было сделано, чтобы подтвердить, что откат будет выполняться без него. В самом деле. - Переместить
@Async
аннотация кHistoryWriter.saveHistory()
метод иметь его в одном месте с@Transactional
. В этой статье https://dzone.com/articles/spring-async-and-transaction предлагается, чтобы она работала таким образом, но для меня откат не выполняется после теста. - Обмен местами этих двух аннотаций. Это также не дает желаемого результата.
Кто-нибудь есть идеи, как принудительно отменить изменения базы данных в асинхронном режиме?
Боковые ноты:
конфигурация сделки:
<tx:annotation-driven proxy-target-class="true" transaction- manager="jpaTransactionManager"/>
Асинхронный конфигурации:
<task:executor id="executorWithPoolSizeRange" pool-size="50-75" queue-capacity="1000" /> <task:annotation-driven executor="executorWithPoolSizeRange" scheduler="taskScheduler"/>
Большое спасибо за ваш ответ. Поскольку я не мог архивировать это, и теперь я знаю, что это невозможно, я закончил создание отдельного Spring config xml для тестирования, в котором удалялась '<задача: аннотация, управляемая исполнителем =" executorWithPoolSizeRange "scheduler =" taskScheduler "/>' so @Async не будет работать во время тестирования, и, таким образом, транзакция будет отменена. – dty
Теперь у меня есть еще одна задача, не могли бы вы взглянуть? Мне нужно было добавить PowerMock в свои тестовые примеры в дополнение к SpringJUnit4ClassRunner. Для этого я добавил '@RunWith (PowerMockRunner.class) @PowerMockRunnerDelegate (SpringJUnit4ClassRunner.class)' И теперь я также хотел бы использовать Parameterized runner. Я проверил https://jira.spring.io/browse/SPR-5292, и, похоже, я могу использовать Spring Rules, чтобы заставить его работать с параметризованным. Но будет ли он работать и с PowerMock? Я попробовал делегировать PowerMock для параметра Parameterized и добавлять правила Spring, но не работал. Это можно сделать? – dty
Я никогда не пробовал эту комбинацию, поэтому я не знаю, работает она или нет. –