Creating unit tests
For unit testing, we are using a JUnit, which is a popular Java-based unit testing library. The following source code shows the example skeleton of the Spring Boot test class. The @SpringBootTest annotation specifies that the class is a regular test class that runs Spring Boot based tests. The @Test annotation before the method defines to JUnit that the method can be run as a test case. The @RunWith(SpringRunner.class) annotation provides Spring ApplicationContext and get beans injected into your test instance:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTestsClass {
@Test
public void testMethod() {
...
}
}
First, we will create our first test case, which will test the major functionality of your application before creating any formal test cases. Open the CardatabaseApplicationTest test class that has already been made for your application. There is one test method called contextLoads where we will add the test. The following test checks that the instance of controller was created and injected successfully:
package com.packt.cardatabase;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.packt.cardatabase.web.CarController;
@RunWith(SpringRunner.class)
@SpringBootTest
public class CardatabaseApplicationTests {
@Autowired
private CarController controller;
@Test
public void contextLoads() {
assertThat(controller).isNotNull();
}
}
To run tests in Eclipse, activate the test class in the Project Explorer and right-click your mouse. Select Run As | JUnit test from the menu. You should now see the JUnit tab in the lower part of the Eclipse workbench. The test results are shown in this tab and the test case has been passed:
Next, we will create unit tests for our car repository to test CRUD operations. Create a new class called CarRepositoryTest in the root test package. Instead of the @SpringBootTest annotation, the @DataJpaTest can be used if the test focuses only on JPA components. When using this annotation the H2 database, Hibernate, and Spring Data are configured automatically for testing. SQL logging will be also turned on. The tests are transactional by default and roll back at the end of the test case. TestEntityManager is used to handle the persist entities and it is designed to be used in testing. You can see in the following, the source code of the JPA test class skeleton:
package com.packt.cardatabase;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;
import com.packt.cardatabase.domain.Car;
import com.packt.cardatabase.domain.CarRepository;
@RunWith(SpringRunner.class)
@DataJpaTest
public class CarRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private CarRepository repository;
// Test cases..
}
We will add out first test case to test the addition of a new car to database. A new car object is created and saved to the database with the persistAndFlush method provided by TestEntityManager. Then, we check that the car ID cannot be null if it is saved successfully. The following source code shows the test case method. Add the following method code into your CarRepositoryTest class:
@Test
public void saveCar() {
Car car = new Car("Tesla", "Model X", "White", "ABC-1234",
2017, 86000);
entityManager.persistAndFlush(car);
assertThat(car.getId()).isNotNull();
}
The second test case will test the deletion of cars from the database. A new car object is created and saved to the database. Then, all cars are deleted from the database, and finally, the findAll() query method should return an empty list. The following source code shows the test case method. Add the following method code into your CarRepositoryTest class:
@Test
public void deleteCars() {
entityManager.persistAndFlush(new Car("Tesla", "Model X", "White",
"ABC-1234", 2017, 86000));
entityManager.persistAndFlush(new Car("Mini", "Cooper", "Yellow",
"BWS-3007", 2015, 24500));
repository.deleteAll();
assertThat(repository.findAll()).isEmpty();
}
Run the test cases and check on the Eclipse JUnit tab that the tests were passed:
Next, we will show how to test your RESTful web service JWT authentication functionality. For testing the controllers or any endpoint that is exposed, we can use a MockMvc. By using the MockMvc, the server is not started but the tests are performed in the layer where Spring handles HTTP requests, and therefore it mocks the real situation. MockMvc provides the perform method to send the requests. To test authentication, we have to add credentials to the request body. We perform two requests; the first has the correct credentials and we check that the status is OK. The second request contains incorrect credentials and we check that we get a 4XX HTTP error:
package com.packt.cardatabase;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class CarRestTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testAuthentication() throws Exception {
// Testing authentication with correct credentials
this.mockMvc.perform(post("/login")
.content("{\"username\":\"admin\", \"password\":\"admin\"}")).
andDo(print()).andExpect(status().isOk());
// Testing authentication with wrong credentials
this.mockMvc.perform(post("/login")
.content("{\"username\":\"admin\", \"password\":\"wrongpwd\"}")).
andDo(print()).andExpect(status().is4xxClientError());
}
}
Now, when we run the authentication tests, we can see that the test passed:
Now, we have covered the basics of testing in the Spring Boot application, and you should have the knowledge required to implement more test cases for your application.