Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Junit: writing a test for a method that deletes an entity?

What would be the most exhaustive tests that I could write for the following piece of code?

public void deleteFromPerson(person person) {
    person = personRepository.returnPerson(person.getId());
    personRepository.delete(person);
}

This method is within a service class. The method makes calls to a JpaRepository that then calls it's delete() method on the entity.

If it is not possible to test if the entity is being deleted, is there any other tests cases I can run on the method?

like image 797
java123999 Avatar asked Jun 28 '16 16:06

java123999


People also ask

How can you use JUnit for testing a code that throws a desired exception?

JUnit provides an option of tracing the exception handling of code. You can test whether the code throws a desired exception or not. The expected parameter is used along with @Test annotation. Let us see @Test(expected) in action.

What is @ignore and when it is used in JUnit?

The @Ignore test annotation is used to ignore particular tests or group of tests in order to skip the build failure. @Ignore annotation can be used in two scenarios as given below: If you want to ignore a test method, use @Ignore along with @Test annotation.

What is JUnit Testsuite?

Test suite is used to bundle a few unit test cases and run them together. In JUnit, both @RunWith and @Suite annotations are used to run the suite tests. This chapter takes an example having two test classes, TestJunit1 & TestJunit2, that run together using Test Suite.


1 Answers

There are two testing strategies. One is unit testing, i.e. making sure your service works. The other is integration/end-to-end testing, i.e. making sure everything plays nicely together.

You unit test stuff you own, you integration test everything you have. This is a pretty rough example using just your statement, plus some made up stuff where I can't fill in the blanks.

Unit Tests

Using Mockito

PersonRepository personRepository = mock(PersonRepository.class);

@TestSubject
PersonService personService = new PersonService(): 

@Test
public void unitTest() {
    personService.setPersonRepository(personRepository);
    Person person = new Person(1L);
    Person person2 = new Person(1L);

    when(personRepository.returnPerson(1L)).thenReturn(person2); //expect a fetch, return a "fetched" person;

    personService.deleteFromPerson(person);

    verify(personRepository, times(1)).delete(person2); //pretty sure it is verify after call
}

Using EasyMock...

@Mock
PersonRepository personRepository; //assuming it is autowired

@TestSubject
PersonService personService = new PersonService(): 

@Test
public void unitTest() {
    Person person = new Person(1L);
    Person person2 = new Person(1L);

    EasyMock.expect(personRepository.returnPerson(1L)).andReturn(person2); //expect a fetch, return a "fetched" person;
    personRepository.delete(person2);
    EasyMock.expectLastCall(); //expect a delete for person2 we plan to delete
    replayAll();

    personService.deleteFromPerson(person);

    verifyAll(); //make sure everything was called
}

Yes, this test looks like it is written rigidly, but that's really all you're testing in the unit test, anyways. You want the DB to fetch a Person from the database using an argument, hence why there are two Person objects, and you expect to delete that passed Person object, which is why you expect the call. Simple method yields simple test. You basically want to ensure you're interacting with your repository as you expect. Repository could be broken or null in actual implementation, but that doesn't change the fact that your service is implemented correctly.

Integration Tests

On the other hand, if you want to do an integration test, no mocking is used. Instead, you'll need to wire up everything like a test DB and repo. I'll leave that up to you since there's no reference for implementation.

@Test
public void integrationTestForAddAndDelete() {
    Person person = createDummyPersonForInsertion(); //static method that creates a test Person for you
    Person comparePerson;
    //make sure we haven't added the person yet
    Assert.assertNull(personService.getPerson(person));

    //add the Person
    comparePerson = personService.addPerson(person);
    Assert.assertNotNull(personService.getPerson(person));
    //add a rigorous compare method to make sure contents are the same, i.e. nothing is lost or transmuted incorrectly, ignoring ID if that is autogen
    //alternatively, you can create a unit test just for Person
    Assert.assertEquals(person, comparePerson); 

    //remove the Person
    personService.deleteFromPerson(person);
    Assert.assertNull(personService.getPerson(person));

    //test for exception handling when you try to remove a non-existent person;
    personService.deleteFromPerson(person);

    //test for exception handling when you try to remove null
    personService.deleteFromPerson(null);
}

In this case, you want to make sure your repo actually handles all the calls from the service. You know your service works from the unit test, but does the repo work from the service or have you configured something wrong

like image 131
Compass Avatar answered Sep 28 '22 02:09

Compass