@RestController
@RequestMapping("/transactions")
public class PaymentTransactionsController {
@Autowired
private PaymentTransactionRepository transactionRepository;
@GetMapping("{id}")
public ResponseEntity<?> get(@PathVariable String id) {
return transactionRepository
.findById(Integer.parseInt(id))
.map(mapper::toDTO)
.map(ResponseEntity::ok)
.orElseGet(() -> notFound().build());
}
JUnit 5测试:
@ExtendWith({ RestDocumentationExtension.class, SpringExtension.class })
@SpringBootTest(classes = PaymentTransactionsController.class)
public class ApiDocumentationJUnit5IntegrationTest {
@Autowired
private ObjectMapper objectMapper;
private MockMvc mockMvc;
@BeforeEach
public void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.apply(documentationConfiguration(restDocumentation)).build();
}
@Test
public void uniqueTransactionIdLenght() {
try {
this.mockMvc.perform(RestDocumentationRequestBuilders.get("/transactions/1")).andExpect(status().isOk())
.andExpect(content().contentType("application/xml;charset=UTF-8"))
.andDo(document("persons/get-by-id"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
PaymentTransactionRepository是我用来定义存储库的接口。可能需要存根请求并返回测试数据吗?我存根请求的适当原因是什么?我得到
Field transactionRepository in org.restapi.PaymentTransactionsController required a bean of type 'org.backend.repo.PaymentTransactionRepository' that could not be found.
答案 0 :(得分:0)
您可以使用@MockBean
在应用程序上下文中创建存储库的存根:
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = PaymentTransactionsController.class)
class ApiDocumentationJUnit5IntegrationTest {
@MockBean
private PaymentTransactionRepository transactionRepository;
...
@BeforeEach
void setUp() {
when(transactionRepository.findById(eq(ID))).thenReturn(mock);
}
@Test
void testSomething(){
...
}
此外,您可以将测试范围更改为DataJpaTest
或使用整个应用程序上下文,并使用真实数据库中准备好的数据运行测试。在这种情况下,您不仅可以测试控制器逻辑,还可以测试整个系统逻辑。
@DataJpaTest
@ExtendWith(SpringExtension.class)
class ApiDocumentationJUnit5IntegrationTest {
@Autowired
private PaymentTransactionRepository transactionRepository;
@Test
void testSomething(){
List<Payment> payments = transactionRepository.findAll();
assertThat(payments).hasSize(3);
...
}
}
要运行此测试用例,需要对测试进行数据库配置。如果您不在应用程序中使用本机查询,则可以使用h2。但是,如果您密集使用本机查询以及目标数据库的一些特殊功能,则可以使用TestContainers库在docker中运行真实的数据库映像,并在该映像上运行测试。
答案 1 :(得分:0)
关于从控制器上下文进行的集成测试,如果您的目标是执行涉及PaymentTransactionRepository
所访问的实际数据源的集成测试。
问题:
为了解决:
Field transactionRepository in org.restapi.PaymentTransactionsController required a bean of type 'org.backend.repo.PaymentTransactionRepository' that could not be found.
或类似的东西,例如:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'paymentTransactionsController': Unsatisfied dependency expressed through field 'transactionRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.data.PaymentTransactionRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.data.PaymentTransactionRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
替换:
@ExtendWith({ RestDocumentationExtension.class, SpringExtension.class })
@SpringBootTest(classes = PaymentTransactionsController.class)
public class ApiDocumentationJUnit5IntegrationTest {
通过:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApiDocumentationJUnit5IntegrationTest {
自:
SpringBootTest:当不使用嵌套的@Configuration且未指定显式类时,自动搜索@SpringBootConfiguration。
请参见Spring Docs
最近您问过,假设findById
类的PaymentTransactionRepository
方法返回Optional<DTO>
的示例DataJpaTest测试示例如下:
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class PaymentTransactionRepositoryIntegrationTest {
@Autowired
PaymentTransactionRepository target;
@BeforeEach
public void setUp() throws Exception {
}
@Test
public void testNotNull() {
assertNotNull(target);
}
@Test
public void testFindByIdFound() {
Optional<DTO> res = target.findById(1L);
assertTrue(res.isPresent());
}
@Test
public void testFindByIdNotFound() {
Optional<DTO> res = target.findById(3L);
assertFalse(res.isPresent());
}
}
请找到here一个简单的示例,该示例具有100%的功能,即使用H2内存数据库预先加载测试数据,并且包含通过测试所需的最低gradle / spring配置。它包括使用SprinbBoot2(JPA)和JUnit5的2种类型的集成测试,1)控制器:ApiDocumentationJUnit5IntegrationTest
和2)仓库:PaymentTransactionRepositoryIntegrationTest
。