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
- How can we
Autowireservice class in test ? I am using constructor ininit()method to create service object. - Do we have to set all
Autowireelement for service class ? For exStubRequestServicehave autowiredRequestDaowhich I need to set explicitly before calling test method otherwise it givedsnullPointerExceptionasrequestDaoisnullinStubRequestService.getRequestmethod. - Which are the good practices to follow while unit testing Spring service layer ? (If I am doing anything wrong).
If you really feel that it will make your tests easier to understand – you can initialize a spring context and fetch all of the objects from there. However, usually it will require creating a separate spring configuration XML file specifically for tests therefore I would not recommend it.
(and 3) Basically, I prefer testing each component of my application in total isolation from eachother and that’s why I do not recommend what I described in [1].
What that means, is you take a separate logical slice of your application and test only it, while fully mocking up everything it tries to access.
Let’s say you have three classes:
Now, what tests can we write here?
DataAccessLayerproperly converts the object from mocked up WS to our domain object.ViewLayerproperly formats the object given to him and writes it to mocked up output stream.Controllertakes an object from mocked upDataAccessLayerprocesses it properly and sends it to mocked upViewLayer.