我的测试用例中预期异常的正确组合是什么?

What is the right combination of expected exceptions in my test case?

在进行一些数据源测试时,我编写了这个小型 EJB。

@Stateless
@Remote(IEmpService.class)
@LocalBean
public class EmpService implements IEmpService {

  @PersistenceContext
  private EntityManager em;

  public void removeAllEmps() {
    em.createQuery("DELETE FROM Emp").executeUpdate();
  }

  public List<Emp> getAllEmps() {
    return em.createQuery("FROM Emp", Emp.class).getResultList();
  }
}

如您所见,有一种方法可以删除条目,另一种方法可以 select。对于我的测试,我创建了一个用户,该用户在 table 上具有 select, insert, update 但没有 delete 权限。所以执行方法getAllEmps会得到一个结果,而removeAllEmps应该会因为权限不足而失败。

我写了这个测试class

@RunWith(Arquillian.class)
public class DataSourceTest {

  @Deployment
  public static JavaArchive createDeployment() {
    // ...
  }

  @EJB
  EmpService testclass;

  @Rule
  public ExpectedException thrown = ExpectedException.none();

  @UsingDataSet("empBefore.xml")
  @Test
  public void testGetAllEmps() {
    List<Emp> allEmps = testclass.getAllEmps();

    Assert.assertEquals(2, allEmps.size());
  }

  @UsingDataSet("empBefore.xml")
  @Test
  public void testDeleteAllEmps() {
    thrown.expect(EJBException.class);
    thrown.expectCause(CoreMatchers.isA(SQLSyntaxErrorException.class));
    
    testclass.removeAllEmps();
  }

}     

虽然 testGetAllEmps 测试工作顺利,但我无法让 testDeleteAllEmps 产生绿色条,因为我没有正确组合“外部”(thrown.excpect) 异常和“内部”(thrown.expectCause) 异常。执行测试方法时,我得到以下堆栈跟踪:

javax.ejb.EJBTransactionRolledbackException: org.hibernate.exception.SQLGrammarException: could not execute statement

[...]

Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement

[...]

... 187 more

Caused by: org.hibernate.exception.SQLGrammarException: could not execute statement

[...]

... 217 more

Caused by: java.sql.SQLSyntaxErrorException: ORA-01031: insufficient privileges

[...]

... 226 more

所以我的期望是,“外部”异常是 EJBTransaction(因为 EJBTransactionRolledbackException 是它的子项),“内部”异常是 SQLSyntaxErrorException。 但是即使我将 thrown.expect 更改为 EJBTransactionRolledbackException and/or 将 thrown.expectCause 更改为 SQLGrammarException 测试仍然没有变绿。

任何人都可以帮助我确定正确的异常组合,我必须期望让我的测试用例 运行 变成绿色条吗? (甚至可能检索异常消息?)

在我看来,第一个异常是 SQLSyntaxErrorException,它引发了 SQLGrammarException,引发了 PersistenceException,引发了 EJBTransactionRolledBackException。所以你可以试试

thrown.expect(EJBException.class);
thrown.expectCause(CoreMatchers.isA(PersistenceException.class));

甚至

thrown.expect(EJBTransactionRolledBackException.class);
thrown.expectCause(CoreMatchers.isA(PersistenceException.class));

但何必呢?仅仅期待 EJBException 而不关心原因是什么还不够吗?