0
@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.
4

2 回答 2

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 文档

DataJpaTest 集成测试

正如您最近所问的,假设类findById方法PaymentTransactionRepository返回 an的示例测试 DataJpaTestOptional<DTO>如下所示:

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

功能示例

请在此处找到一个简单的示例,100% 功能化,即使用 H2 内存数据库预加载测试数据,并包含通过测试所需的最低 gradle/spring 配置。它包括使用 SprinbBoot2 (JPA) 和 JUnit5 的 2 种类型的集成测试,1) 控制器:ApiDocumentationJUnit5IntegrationTest和 2) 存储库:PaymentTransactionRepositoryIntegrationTest.

于 2018-12-14T02:55:40.617 回答
0

您可以使用 a@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 中运行您的真实数据库映像并在此映像上运行测试。

于 2018-12-11T23:06:02.410 回答