Junit测试场景不执行回滚。

huangapple go评论65阅读模式
英文:

Junit test scenario doesn't perform rollback

问题

以下是您要翻译的代码部分:

我有以下测试需要展示我的事务可以正常工作并进行回滚问题在于我的RuntimeException在数据插入数据库之前就被执行了因此回滚没有发生如何设置这个测试

@Test
@Rollback(true)
public void testForTransactionRollback() throws ClassNotFoundException, SQLException {

    User user = new User();
    user.setFirstName("Ivan");
    user.setLastName("Ivanov");
    user.setPhoneNumber("18000000");
    user.setEmail("mail@gmail.com");
    user.setCardNumber("4111111111111111");
    user.setDeliveryAddress("address");
    user.setComment("comment");

    String result = "";

    final ClientDAO clientDao1 = Mockito.spy(new ClientDAOImpl());

    final ClientDAOImpl clientDaoImpl = (ClientDAOImpl) clientDao1;

    Mockito.when(clientDao1.insert(user)).thenThrow(new RuntimeException());

    try {
        clientDao1.insert(user);
    } catch (final RuntimeException e) {
        System.out.println("Expected failure to trigger transaction caught");
    } finally {
        user = clientDao1.get(1L);
        if (user != null) {
            result = user.getFirstName();
        }
    }
    Assert.assertEquals("它应该相等", "", result);
}

请注意,这是您提供的代码的翻译部分。如果您需要更多帮助或有其他问题,请随时提出。

英文:

I have the following test where I need to show that my transaction works and can do rollback. The problem here is my RuntimeException is executed before the data is entered into the database. So rollback doesn't happen. How do I set up this test?

@Test
@Rollback(true)
public void testForTransactionRollback() throws ClassNotFoundException, SQLException {

    User user = new User();
    user.setFirstName("Ivan");
    user.setLastName("Ivanov");
    user.setPhoneNumber("18000000");
    user.setEmail("mail@gmail.com");
    user.setCardNumber("4111111111111111");
    user.setDeliveryAddress("address");
    user.setComment("comment");

    String result = "";

    final ClientDAO clientDao1 = Mockito.spy(new ClientDAOImpl());

    final ClientDAOImpl clientDaoImpl = (ClientDAOImpl) clientDao1;

    Mockito.when(clientDao1.insert(user)).thenThrow(new RuntimeException());

    try {
        clientDao1.insert(user);
    } catch (final RuntimeException e) {
        System.out.println("Expected failure to trigger transaction caught");
    } finally {
        user = clientDao1.get(1L);
        if (user != null) {
            result = user.getFirstName();
        }
    }
    Assert.assertEquals("it should be equal", "", result);
}

答案1

得分: 1

我认为你面临的问题是由两个内部事务引起的(一个嵌套在另一个内部事务内部):第一个在clientDao1.insert(user)内,第二个在你的测试中(假设你已经用@Transactional@DataJpaTest注解了测试类,但你没有显示出来)。如果在内部事务中抛出了RuntimeException,这是因为

Mockito.when(clientDao1.insert(user)).thenThrow(new RuntimeException());

这意味着你的内部clientDao1.insert方法无法从该异常中恢复,而外部方法(测试方法)无法发挥作用。

这就是为什么数据永远不会被写入数据库,甚至不会被持久化(当然,如果你使用Hibernate作为你的JPA提供程序,那么会使用Hibernate缓存)。

英文:

I think the problem you're facing is caused by two inner transactions (one inside the other): first one is inside clientDao1.insert(user) and a second one inside your test (providing that you annotated your test class with @Transactional or @DataJpaTest, but you've not shown that). If RuntimeException is thrown within inner transaction, which is the case because of

Mockito.when(clientDao1.insert(user)).thenThrow(new RuntimeException());

then it means your inner clientDao1.insert method cannot recover from that exception and the outer method (test one) has nothing to say.

That's why data will NEVER be written to the database or even persisted (hibernate caching, of course if you use hibernate as your JPA provider).

huangapple
  • 本文由 发表于 2020年8月5日 00:19:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63251046.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定