Search code examples
javaspringunit-testingspring-bootspring-boot-test

Should we write unit test and integration test for repository layer in Spring Boot?


I have a bunch of questions regarding Spring Boot repository layer.

My questions are:

  1. Should we even write both unit test and integration test for a repository layer in Spring Boot that does not have any custom code or query?
  2. What's the best approach to write an integration test for repository layer in Spring Boot? I have listed both the approaches below. Among both the approaches which one is better. Is there any best practice where I should be following one over the other?
  3. If the answer to my above question #1 is yes, then how do I write a unit test for the repository layer in Spring Boot?

CurrencyRepository.java

@Repository
public interface CurrencyRepository extends CrudRepository<Currency, String> {

}

Since this uses an embedded H2 DB it is an integration test and not a unit test. Is my understanding correct?

CurrencyRepositoryIntegrationTest.java (Approach 1)

@RunWith(SpringRunner.class)
@DataJpaTest
public class CurrencyRepositoryIntegrationTest {

    @Autowired
    private TestEntityManager entityManager;
    @Autowired
    private CurrencyRepository repository;

    @Test
    public void testFindByName() {
        entityManager.persist(new Currency("USD", "United States Dollar", 2L));
        Optional<Currency> c = repository.findById("USD");
        assertEquals("United States Dollar", c.get().getCcyNm());
    }

}

CurrencyRepositoryIntegrationTest2.java (Approach 2)

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class CurrencyRepositoryIntegrationTest2 {

    @Autowired
    private CurrencyRepository repository;

    @Test
    public void testFindByName() {
        repository.save(new Currency("USD", "United States Dollar", 2L));
        Optional<Currency> c = repository.findById("USD");
        assertEquals("United States Dollar", c.get().getCcyNm());
    }

}

Solution

  • For the integration test, there's the old saying "Don't Mock What You Don't Own". See e.g. https://markhneedham.com/blog/2009/12/13/tdd-only-mock-types-you-own/ and https://8thlight.com/blog/eric-smith/2011/10/27/thats-not-yours.html

    The JUnit test you would write would mock the underlying EntityManger to test if spring was implemented correctly. That's a test that we hope the spring developers already have, so I wouldn't repeat it.

    For the integration test, I guess you don't care how or if the repository uses an EntityManager underneath. You just want to see if it's behaviour is correct. So the second approach fits better.