Spring Boot集成测试示例

学习使用@SpringBootTestJunit 5为给定的Spring rest控制器api 编写集成测试。这项技术可以同时应用于Spring Boot和Spring MVC应用程序。

1.集成测试中要测试的内容

在Spring Boot应用程序中进行集成测试时,请记住:

  • 集成测试应该用来测试不同模块是否正确绑定以及它们是否按预期工作。
  • 集成测试不应利用实际的生产依赖关系(例如数据库/网络),它们可以模仿某些行为。
  • 该应用程序应在ApplicationContext中运行并在其中运行测试。
  • Spring Boot提供了@SpringBootTest注解,该注解将启动嵌入式服务器,创建一个Web环境,然后启用@Test方法进行集成测试。使用它的webEnvironment属性。
  • 它还创建了ApplicationContext我们的测试中使用过的。
  • 最好使用h2内存数据库来模拟数据库。尽管这不是强制性的,但我们可以使用Mockito模拟数据库交互。
  • 建议使用带有@TestConfiguration注解的测试特定配置

提示: Spring Boot提供了许多专门的注解来测试应用程序的某些部分,例如@WebMvcTest测试Web层或@DataJpaTest以后测试持久性。

使用@SpringBootTest了覆盖从传入请求数据库整个Spring Boot应用程序的测试。

2.使用@SpringBootTest和Junit 5编写集成测试

2.1。Maven依赖

首先包括必需的依赖项。我们需要使用spring-boot-starter-test,它将在内部使用spring-test和其他依赖库。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>

	<!-- exclude junit 4 -->

	<exclusions>
		<exclusion>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</exclusion>
	</exclusions>
</dependency>

<!-- Junit 5 -->
<dependency>
	<groupId>org.junit.jupiter</groupId>
	<artifactId>junit-jupiter-api</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.jupiter</groupId>
	<artifactId>junit-jupiter-engine</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-launcher</artifactId>
	<scope>test</scope>
</dependency>

2.2。REST控制器

这是Spring boot rest控制器,我们将为其编写测试。

  • 控制器对EmployeeRepository类具有持久性。
  • getEmployees()方法返回所有雇员的列表。通常,在实际应用中,它将接受分页参数
  • addEmployee() api需要使用访问请求上下文ServletUriComponentsBuilder
  • addEmployee() api使用ResponseEntity类返回HTTP状态和标头。
import java.net.URI;
import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.how2codex.rest.dao.EmployeeRepository;
import com.how2codex.rest.model.Employee;
import com.how2codex.rest.model.Employees;

@RestController
public class EmployeeController 
{
	@Autowired
    private EmployeeRepository employeeRepository;

	@GetMapping(path="/employees", produces = "application/json")
    public Employees getEmployees() 
    {
		Employees response = new Employees();
		ArrayList<Employee> list = new ArrayList<>();
		employeeRepository.findAll().forEach(e -> list.add(e));
		response.setEmployeeList(list);
        return response;
    }
    
    @PostMapping(path= "/employees", consumes = "application/json", produces = "application/json")
    public ResponseEntity<Object> addEmployee(@RequestBody Employee employee) {       
                
        //add resource
    	employee = employeeRepository.save(employee);
        
        //Create resource location
        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                                    .path("/{id}")
                                    .buildAndExpand(employee.getId())
                                    .toUri();
        
        //Send location in response
        return ResponseEntity.created(location).build();
    }
}

2.3。整合测试

下面给出的测试类包含上述Spring Boot 支架控制器的集成测试。这个测试班:

  • 使用@SpringBootTest注解加载实际的应用程序上下文。
  • 使用WebEnvironment.RANDOM_PORT在某个随机服务器端口上创建运行应用程序。
  • @LocalServerPort获取服务器已启动的端口的引用。它有助于构建实际的请求URI,以模拟实际的客户端交互。
  • 使用TestRestTemplate类有助于调用由控制器类处理的HTTP请求。
  • 如果测试依赖于@Sql注解,则可以使用一些先决条件数据来填充数据库以正确测试行为。
  • org.junit.jupiter.api.Test 注解来自Junit 5,并将该方法标记为要运行的测试方法。
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.jdbc.Sql;
import com.how2codex.rest.model.Employee;
import com.how2codex.rest.model.Employees;

@SpringBootTest(classes = SpringBootDemoApplication.class, 
		webEnvironment = WebEnvironment.RANDOM_PORT)
public class EmployeeControllerIntegrationTests 
{
	@LocalServerPort
	private int port;

	@Autowired
	private TestRestTemplate restTemplate;

	@Sql({ "schema.sql", "data.sql" })
	@Test
	public void testAllEmployees() 
	{
		assertTrue(
				this.restTemplate
					.getForObject("http://localhost:" + port + "/employees", Employees.class)
					.getEmployeeList().size() == 3);
	}

	@Test
	public void testAddEmployee() {
		Employee employee = new Employee("Lokesh", "Gupta", "mobtrack_service@163.com");
		ResponseEntity<String> responseEntity = this.restTemplate
			.postForEntity("http://localhost:" + port + "/employees", employee, String.class);
		assertEquals(201, responseEntity.getStatusCodeValue());
	}
}

3.演示

在IDE中运行上述测试。我用过Eclipse。测试类在嵌入式服务器中启动整个应用程序,并逐个执行每个测试。

图片

4。结论

在这个使用Junit 5的Spring Boot集成测试示例中,我们学习了编写测试以在单个测试中测试多层应用程序的测试。他们验证控制器层和持久层是否一起正常工作。

在集成测试中,我们不需要使用实际的Web服务器来运行应用程序,但是我们可以肯定地在Spring Boot中使用嵌入式服务器。

saigon has written 1445 articles

Leave a Reply