を使用して統合テストを作成していSpringJUnit4ClassRunner
ます。私は基本クラスを持っています:
@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();
}
フローの最後に、エンティティが DB に保存されます。ただし、ここでの要件は、非同期で実行する必要があるということです。したがって、このメソッドが呼び出されると考えてください。
@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
オブジェクトが DB に残されることです。最終的にすべての変更をロールバックするには、テスト トランザクションを作成する必要があります。
今、私がこれまでに試したこと:
@Async
注釈を削除します。明らかに、これは解決策にはなりませんが、それなしでロールバックが実行されることを確認するために行われました。確かにそうです。@Async
アノテーションをHistoryWriter.saveHistory()
メソッドに移動して、 で 1 か所にまとめ@Transactional
ます。この記事https://dzone.com/articles/spring-async-and-transactionは、この方法で動作することを示唆していますが、私にとっては、テスト後にロールバックは行われません。- これら 2 つの注釈の場所を入れ替えます。それは望ましい結果も与えません。
非同期メソッドで行われた DB 変更のロールバックを強制する方法を知っている人はいますか?
補足:
トランザクション構成:
<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"/>