简体   繁体   中英

Junit4 : expected=Exception not working with SPRING

I'm trying to use the @Test(expected = RuntimeException.class) annotation in order to test for an expected exception. My code is as follows:

@Test(expected = RuntimeException.class)
    public void testSaveThrowsRuntimeException(){

                    User user = domain.save(null);

    }

and my save method simple like this :

public User save(User newUser) { 
         if(newUser == null) { 
            throw new RuntimeException(); 
         }
         //saving code goes here
    }

after debugging the code I found that code throwing the exception as expected but its getting eaten somewhere in between in spring framework classes.

I tried the same with old way (try catch block) but still I am not able to catch that exception in test and test keeps throwing errors in runafter method of Junit :

org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1031)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:504)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:277)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:170)
at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:344)
at org.springframework.test.context.junit4.SpringMethodRoadie.runAfters(SpringMethodRoadie.java:307)
at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:338)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:142)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: javax.transaction.RollbackException
at org.objectweb.jotm.TransactionImpl.commit(TransactionImpl.java:245)
at org.objectweb.jotm.Current.commit(Current.java:488)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1028)
... 23 more

And I am sure this is because of that RuntimeException I am throwing in save but not able catch it or pass the test with expected clause.

anybody have any idea whats going wrong?

Turned out that my first answer was wrong. Both @Test(expected=...) and @ExpectedException work, but there is some incompability between the Spring TestContext and Junit 4.5 . Using Junit 4.4 solved the problem for me. Finally.

Here's a work-around I found to with Junit 4.5 - separate the @Transactional and @ExpectedException into nested functions. I guess the problem is something to do with the aop stuff spring puts around a @Transactional method.

@Test
@ExpectedException(org.springframework.dao.DataIntegrityViolationException.class)
public void Test10UniqueName()
{
    DoTest10UniqueName();
}

@Transactional
public void DoTest10UniqueName()
{
    final String NAME = "NAME";
    ProductCategoryDAO dao = DAOFactory.getProductCategoryDAO();
    ProductCategory test1 = new ProductCategory();
    test1.setName(NAME);
    ProductCategory test2 = new ProductCategory();
    test2.setName(NAME);
    dao.save(test1);
    dao.save(test2);
}

Either you're running a unit test, in which case Spring TX shouldn't come in to play, or you're running some kind of integration test where you want to test what the save method does when your runtime exception is swallowed. I don't think anything is going wrong, you just need to make sure you understand what it is you are trying to test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM