Unit testing with Mockito

I am writing unit tests for a service level in a spring application.
Here is my class of service

@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); } } 

Works fine, but I have few questions.

  • How can we Autowire class of service in the test? I use the constructor in the init() method to create the service object.
  • Do I need to install all Autowire elements for a service class? For ex, the StubRequestService has an autwired RequestDao , which I must set explicitly before calling the test method, otherwise it gave a nullPointerException as RequestDao is null in StubRequestService.getRequest .
  • What are the best practices to follow when testing spring devices? (If I do something wrong).
+6
source share
3 answers
  • If you really feel that this will simplify your tests, you can initialize the spring context and extract all the objects from it. However, this usually requires creating a separate spring XML configuration file specifically for tests, so I would not recommend it.

     ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testApplicationContext.xml"); stubRequestService = (RequestService)applicationContext.getBean("myRequestServiceBean"); 
  • (and 3) In principle, I prefer to test each component of my application in complete isolation from eachother, and therefore I do not recommend what I described in [1].

What does this mean, you take a separate logical fragment of your application and check only , and completely ridicule everything that it is trying to access.

Let's say you have three classes:

 //Fetches stuff from some webservice and converts to your app domain POJOs class DataAccessLayer { public void setWebservice(Webservice ws) {...}; public MyObject getMyObject() {...}; } //Formats the domain POJOs and sends them to some kind of outputstream or stuff. class ViewLayer { public void setOutputStream(OutputStream os) {...}; public void viewMyObject(MyObject mo) {...}; } //Main entry point of our MyObject fetch-process-display workflow class Controller { public void setDataAccessLayer(DataAccessLayer dal) {...}; public void setViewLayer(ViewLayer vl) {...}; public void showMyObject() { MyObject mo = dal.getMyObject(); ...some processing here maybe... vl.viewMyObject(mo); } } 

Now, what tests can we write here?

  • Check if DataAccessLayer correctly converts an object from a fake WS to our domain object.
  • Check if the ViewLayer correctly formats the object provided to it and writes it to the original output stream.
  • We test if the Controller takes an object from mocked up DataAccessLayer processes it correctly and sends it to the mocked ViewLayer .
+3
source

Your test is wonderful. It should not even have the @ContextConfiguration annotation.

An entire dependency injection infrastructure, such as Spring, should be able to provide unit tests with services by simply instantiating them, installing mock dependencies, and then calling their methods.

You are doing it right. For such unit tests, you do not need to have a Spring context. That's why they are called unit tests: they test it against all of their actual dependencies, including Spring.

Side note: if you are using JUnit, the arguments to the assertXxx method must be replaced. The expected value comes before the actual value. This becomes important when the statement fails, and you have a message like "expecting 6, but it was 3", and not "expecting 3, but it was 6".

+7
source

Or you can use springockito https://bitbucket.org/kubek2k/springockito/wiki/Home , this will make your tests cleaner

+3
source

Source: https://habr.com/ru/post/904596/


All Articles