Spring Data: Service layer unit testing

java, spring, spring-data, unit-testing

Solution

Question might be a bit old but I will put an answer in case someone stumbles across.

- I'm using Mockito and JUnit.

- AccountRepository is a plain spring data repository extending JPARepository.

- Account is a plain JPA entity.

To test your services and mock Spring Data repositories, you need something like below.

package foo.bar.service.impl;

import foo.bar.data.entity.Account;
import foo.bar.data.repository.AccountRepository;
import foo.bar.service.AccountService;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceImplTest {

    @Mock
    private static AccountRepository accountRepository;

    @InjectMocks
    private static AccountService accountService = new AccountServiceImpl();

    private Account account;

    @Test
    public void testFindAccount() {

        Integer accountId = new Integer(1);

        account = new Account();
        account.setId(accountId);
        account.setName("Account name");
        account.setCode("Accont code");
        account.setDescription("Account description");

        Mockito.when(accountRepository.findOne(accountId)).thenReturn(account);

        Account retrivedAccount = accountService.findAccount(accountId);

        Assert.assertEquals(account, retrivedAccount);

    }

}

Problem

In my project I'm having trouble doing unit testing. One issue is that just doing an integration test is much faster to write and also tests that the components actually work together. Unit testing novel "algorithms" or so seems much easier. Unit Testing service classes it just feels wrong and useless. I'm using mockito to mock spring data repository (and hence DB access). The thing is if i tell the mocked repository to return entity A on method call getById it will obviously return that and the service will return it too. Yes, the service does some extra stuff, but very minor things, like load lazy collections (from hibernate). Obviously I don't have any lazy collections (proxies) in a unit test. Example: ``` @Test public void testGetById() { System.out.println("getById"); TestCompound expResult = new TestCompound(id, "Test Compound", "9999-99-9", null, null, null); TestCompoundRepository mockedRepository = mock(TestCompoundRepository.class); when(mockedRepository.findOne(id)).thenReturn(expResult); ReflectionTestUtils.setField(testCompoundService, "testCompoundRepository", mockedRepository, TestCompoundRepository.class); TestCompound result = testCompoundService.getById(id); assertEquals(expResult, result); } ``` hooray, the rest succeeds. What a surprise! Not really no. Can some one explain to me what I'm doing wrong? Or else what the point of such a test is? I mean I tell to return expResult and then it is returned. Wow. What a surprise! Feels like I'm testing if mockito works and not my Service. EDIT: The only benefit I see if some were stupid error happens like leaving an unwanted line there that sets return value to null or something similar stupid. Such cases would be caught by the unit test. Still the "reward-effort" ratio seems bad?

Original source