JUnit Test for database exception for duplicate records

3.5k views Asked by At

I need test my database that, when I insert duplicate value in specific column where I have constraint, it fire exception. Can you show me how can I simulate second same call and fire exception?

here is my code, but doesn't work:

@RunWith(MockitoJUnitRunner.class)
public class SomeTestClass {

    @InjectMocks
    private FooService service = new FooServiceImpl();

    @Test(expected = DataIntegrityViolationException.class)
    public void myTest() {
       // init Foo object here

       service.createFoo(myFoo); // here should pass

       service.createFoo(myFoo); // here shouldn't
    }
}

I can't show original FooServiceImpl but the basic concept is here:

@Transactional
public void createFoo(Foo foo) {
   MainFoo mainFoo = new MainFoo();

   SomeObj obj1 = objService.findOne(foo.getId());

   mainFoo.setObj(obj1);

   fooRepository.save(mainFoo);
}

What I do wrong? Thanks.

2

There are 2 answers

7
Yati Sawhney On BEST ANSWER

I am not really sure if you want to test your actual database or you just need to mock the DB call.In case you just want to test your service class better mock the second statement using.

doThrow(ExpectedException).when(mockedObject).methodReturningVoid(...);

Also, If you are using spring, All you need to do is use @InjectMocks and mock the dependencies of the respected class using @Mock.

For consecutive calls you can use:

Mockito.when(repo.findOne(Matchers.anyString())).thenReturn(yourObject).thenThrow(EXCEPTION_OBJ)
0
davidxxx On

I need test my database that, when I insert duplicate value in specific column where I have constraint, it fire exception.

To perform a assertion that checks that the database constraint is there and does its job, you should perform a test without mock and with an in-memory database.

The H2 database is good for that.
Before invoking the method, add in your in-memory database a recording for the Foo entity. You can do it with the EntityManager or your service, whatever. Then invoke your method.

Example of what your test should look like:

@RunWith(SpringJUnit4ClassRunner.class)
public class SomeTestClass {

    private FooService service = new FooServiceImpl();

    @Autowired
    private EntityManager em;

    @Test(expected = DataIntegrityViolationException.class)
    public void myTest() {    
       Foo fooWithXxxValueInBarColumn= new ...();
       em.persist(fooWithXxxValueInBarColumn);
       Foo newFooWithSameXxxValueInBarColumn = new ...();
       service.createFoo(newFooWithSameXxxValueInBarColumn); 
    }
}

Of course, you have to configure your test context to use a in-memory database and not your real database.