So I have a class:
@Service
public class MyService {
@Autowired
private RepositoryA repoA;
@Autowired
private RepositoryB repoB;
@Transactional
public void storeEntity(SomeEntity e) {
repoA.save(e);
OtherEntity o = doSomethingWithEntity(e);
repoB.save(o);
}
}
My method storeEntity
does two saves to two different datasources. I expect that if a save to repoB fails, or doSomethingWithEntity
fails, repoA.save(e)
will be rollbacked.
I want to write a small tests that assures that behaviour:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceForTransactionTest {
@Autowired
private MyService subject;
@Autowired
private RepositoryA repoA;
@MockBean
private RepositoryB repoB;
@Test
public void repoBShouldNotHaveEntries() {
// given
when(repoB.save(any())).thenThrow(new IllegalStateException("Something wrong with db"));
assertThat(repoB.count()).isEqualTo(0);
// when
SomeEntity e = ...
subject.storeEntity(e);
// then
assertThat(repoA.count()).isEqualTo(0);
}
}
This won't work, because exception is thrown and fails the test. When I surround the call with try/catch, then my assertion fails with a message that repoA has 1 entry. How to tackle this?
I also tried this:
@Test
public void repoBShouldNotHaveEntries() {
// given
when(repoB.save(any())).thenThrow(new IllegalStateException("Something wrong with db"));
assertThat(repoB.count()).isEqualTo(0);
// when
SomeEntity e = ...
try {
subject.storeEntity(e);
} catch (Exception e) {
// some output here
}
// then
assertThat(repoA.count()).isEqualTo(0);
}
Assertion fails. I tried also this:
@Test
public void repoBShouldNotHaveEntries() {
// given
when(repoB.save(any())).thenThrow(new IllegalStateException("Something wrong with db"));
assertThat(repoB.count()).isEqualTo(0);
// when
SomeEntity e = ...
subject.storeEntity(e);
}
@After
public void tearDown() {
// then
assertThat(repoA.count()).isEqualTo(0);
}
}
Also fails. 1 record is found, but I expect that @Transactional
should be rolled back.