Skip to content

CT Unit Tests

kapilkalra04 edited this page Mar 23, 2018 · 8 revisions

NOTE: Either perform a JUnit + Mockito - based unit tests with no Spring auto-wiring or perform Spring integration tests with use of autowiring. Don't mix these two.

When we mix autowiring with test doubles from Mockito, autowiring wins and the code throws an exception.


Writing Unit Tests for BITS Darshini

As mentioned above, for writing unit tests for a class we resort to using JUnit and Mockito to carry out the required operations. So it's necessary to follow the below mentioned steps:

1. Check if the class for which you are creating tests needs any refactoring to be done.

Make use of @Data annotation as explained here. This will be useful when we create the test-class. Also Check if any class dependency hasn't been auto-wired. Autowiring helps us perform Dependecy Injection which is required to write an extensive Unit-Test. We use Field Autowiring, instead of Constructor or Setter Autowiring as Mockito has a restriction of creating Mocks for only either of the three and writing code for the latter two is very troublesome. To understand how to autowire dependencies/ understand what it is refer this

2. Writing a ConfigClass for your concerned class.

After you have Autowired your concerned class' dependencies, the concerned class receives them as Beans through the Spring IoC container or we explicitly provide them through a Config Class. To understand what beans are, refer this. As an example consider Class SaveRepository. So, now any beans that have to be provided to it explicitly are provided through its config class which will rightly be named as SaveRepositoryConfig. (Naming Conventioned followed - Add "Config" after the concerned class' Class Name").

As SaveRepository is present in /src/main/java/in/ac/bits/protocolanalyzer/persistence/repository package, the corresponding config class will also have a similiar path url. In the case of SaveRepositoryConfig it will be present inside /src/main/java/config/in/ac/bits/protocolanalyzer/persistence/repository package.

The final step is to use the @ComponentScan annotation in our concerned class' (SaveRepository) class-definition. Refer this so as to understand why it is done.

3. Adding the explicitly created beans in the Config Class to our Integration Tests Config Class.

As we provide our Concerned Class (SaveRepository) the beans it needs through its Config Class (SaveRepositoryConfig) at runtime, we need to simulate the same behavior for our Integeration Tests as well. What this means is that the Beans created in the SaveRepositoryConfig are needed to be added in the config class of our Integration Test(named: ExperimentTest) which is ExperimentTestConfig. So simply add all the bean creation code from ConcernedClassConfig to IntegrationTestConfig (SaveRepositoryConfig to ExperimentTestConfig)

NOTE: As of now we have only 1 Integration Test (ExperimentTest) , we do this only for its Config Class. If there are more Integration Tests in place, then we will have to repeat this step of copying bean declarions for the concerned class to all of the Integration Test Configs in existence.

4. Creating the Test Class.

Continuing with our example, the Test Class for SaveRepository is SaveRepositoryTest. (Naming Convention Followed - Add "Test" after the Class under Test's Class Name). As SaveRepository had /src/main/java/in/ac/bits/protocolanalyzer/persistence/repository as its classpath, the corresponding Unit-Testing Class (in this example SaveRepositoryTest will be rightly located in the /src/test/java/unit/in/ac/bits/protocolanalyzer/persistence/repository package.

To start-off with writing the tests, we to annotate our Test Class with @RunWith(MockitoJUnitRunner.class). This tells Spring that the Runner Class for the particular Test Class is Mockito. Next step is to create mocks/spies of the fields that are being Autowired in the Class under Testing. We can use Mockito's Annotations here. We use @Mock or @Spy just before declaring those Class-Dependency fields (Fields that are autowired in the Class under Testing) in the Test Class.

After this we can begin writing the Tests. Like in any other Unit Test, we first create an object of the Class under Testing but this time we also annotate it with @InjectMocks. This tells Spring where those mocks created are to be injected into. So the next logical step is to call for the injection of the Mocks (perform dependency injection) into the Class under Testing's newly created object. This is done by the MockitoAnnotations.initMocks(this) command. This command is usually written inside one of the @Before methods. By doing this our Test Object is ready to be tested before every Test Function is called upon by the Mockito Runner Class. We write tests the usual way, by adding the @Test annotation over the test function. Inside these test functions we use numerous assert statements. To assert things we use the extensive library of Hamcrest Asserts instead of JUnit Asserts.

Clone this wiki locally