Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing with Mockito

I am writing unit tests for service layer in my spring application.
Here is my service class

    @Service
    public class StubRequestService implements RequestService {    
        @Autowired
        private RequestDao requestDao;  

        @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
        @Override
        public Request getRequest(Long RequestId) {
            Request dataRequest = requestDao.find(requestId);
            return dataRequest;
        }
    }  

Here is my test class

@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" })
public class StubRequestServiceTest {

    @Mock
    public RequestDao requestDao;

    StubRequestService stubRequestService;  // How can we Autowire this ?

    @org.junit.Before
    public void init() {
      stubRequestService = new StubRequestService();  // to avoid this 
      stubRequestService.setRequestDao(dataRequestDao);  
      // Is it necessary to explicitly set all autowired elements ?  
      // If I comment/remove above setter then I get nullPointerException 
    }

    @Test
    public void testGetRequest()  {
        Request request = new Request();
        request.setPatientCnt("3");
        when(requestDao.find(anyLong())).thenReturn(request);
        assertEquals(stubRequestService.getRequest(1234L).getPatientCnt(),3);
    }    
}   

Its working fine but I have few questions

  1. How can we Autowire service class in test ? I am using constructor in init() method to create service object.
  2. Do we have to set all Autowire element for service class ? For ex StubRequestService have autowired RequestDao which I need to set explicitly before calling test method otherwise it giveds nullPointerException as requestDao is null in StubRequestService.getRequest method.
  3. Which are the good practices to follow while unit testing Spring service layer ? (If I am doing anything wrong).
like image 545
Ajinkya Avatar asked Dec 28 '11 12:12

Ajinkya


1 Answers

Your test is fine. It doesn't even have to have the @ContextConfiguration annotation.

The whole point of dependency injection frameworks like Spring is to be able to unit test services by simply instantiating them, setting mock dependencies, and then call their methods.

You're doing it correctly. You don't need to have a Spring context for such unit tests. That's why they're called unit tests: they test it in isolation of all their actual dependencies, Spring included.

Side note: assuming you're using JUnit, the arguments of the assertXxx method should be swapped. The expected value comes before the actual value. It becomes important when the assertion fails and you have a message like "expecting 6 but was 3" rather than "expecting 3 but was 6".

like image 165
JB Nizet Avatar answered Nov 26 '22 04:11

JB Nizet