【问题标题】:Percisely configure spring junit 5 test config精确配置 spring junit 5 测试配置
【发布时间】:2020-08-10 14:43:18
【问题描述】:

使用 spring-boot 和 junit5 编写单元测试相当困难。 我已经阅读了很多文章和一些 junit5 文档,但没有找到任何有用的东西(或者我只是瞎了眼)。

测试:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ScoreTestConfiguration.class)
@AutoConfigureMockMvc
public class ScoreControllerTest {

private static final String SCORE_ENDPOINT = "/scoring";

private static final ObjectMapper MAPPER = new ObjectMapper();

@Autowired
private MockMvc mockMvc;
@MockBean
private ScoreService mockScoreService;

@BeforeEach
public void setUp() {
    ScoreResponseDto response = getScoreResponseDto();
    when(mockScoreService.getScore(any(),any(),any(),any(),any(),any())).thenReturn(response);
}

@NotNull
private ScoreResponseDto getScoreResponseDto() {
    ScoreResponseDto response = new ScoreResponseDto();
    response.setCid("qwe13423qw");
    response.setData(new ScoreResponseDto.ScoringData(0.78f));
    return response;
}


@Test
public void sendValidRequest_getResponse_andOkStatus() throws Exception {
    String request = SCORE_ENDPOINT +
            "/380715346789" + //msisdn
            "?score_formula=1234" +
            "&clientId=5678" +
            "&cid=543" +
            "&stateType=" + StateType.ACTIVE.name() +
            "&subscriberType=" + SubscriberType.POSTPAID.getValue();
    String jsonResponse = MAPPER.writeValueAsString(getScoreResponseDto());
    System.out.println("jsonResponse: " + jsonResponse);
    mockMvc.perform(get(request))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(content().string(jsonResponse));
}

}

配置(这是一个只获得某些特定类的实验,但我失败了):

@Configuration
@ComponentScan(basePackages = "com.some.path.to.rest")
class ScoreTestConfiguration {

}

在执行测试时,我假设全局上下文已启动,尽管我指定在 @Configuration 类中仅加载其中的一部分。

我的问题是如何控制和设置 spring-boot 和 junit5 测试的测试上下文的精确配置。

实际上,如果有人能提供一些关于组织本地测试框架的最佳实践的参考,我将不胜感激。 提前谢谢!

【问题讨论】:

  • 放弃您的测试配置,因为这会破坏 Spring Boot 应用程序的正确初始化以进行测试。如果您的目标是仅测试控制器,请使用 @WebMvcTest 而不是成熟的 @SpringBootTest。
  • 我已经开始使用这种方法并测试尝试加载完整的上下文
  • 这就是@SpringBootTest 的全部意义,如果这不是您想要的,请不要使用@SpringBootTest。
  • 如果目标是避免为控制器测试设置 Spring 上下文,您可能希望使用 MockMvcBuilders 并准备一个独立的 MockMvc。

标签: java spring-boot testing junit5


【解决方案1】:

如果不查看更多代码,就很难判断为什么您的测试配置不能满足您的需求。我创建了一个示例项目,其中包含一些与您的案例和其他案例类似的不同示例 - 您可以找到它here on GitHub。以下是您可以在其中找到的示例列表以及简短说明。


@SpringBootTest(classes = TestedController.class)
@AutoConfigureMockMvc
public class TestWithoutConfiguration {

    @Test
    void fails() {

    }

}

此测试失败,因为没有提供任何配置(除了控制器 bean) - 找不到和注入任何 bean。


@SpringBootTest(classes = {TestedController.class, TestConfiguration.class})
@AutoConfigureMockMvc
public class TestWithTestButWithoutMockBeanConfiguration {

    @Test
    void fails() {

    }

}

这里我们使用了一个为控制器提供服务 bean 的测试配置,但我们仍然缺少该服务使用的 bean - MockedUtilInterface(见下文)。


@SpringBootTest(classes = {TestedController.class, TestConfiguration.class})
@AutoConfigureMockMvc
public class TestWithTestConfiguration {

    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private MockedUtilInterface mockedUtil;

    @Test
    void test() throws Exception {
        when(mockedUtil.value())
                .thenReturn(100);

        mockMvc.perform(get("/test"))
               .andExpect(content().string("100 - rest service from component scan value"));
    }

}

此测试通过 - TestConfiguration 提供服务 bean,我们还创建了一个 MockedUtilInterface bean 作为模拟。 mock被注入到测试配置指向的服务中,服务被注入到实际的控制器中。


@SpringBootTest
@AutoConfigureMockMvc
public class TestWithActualConfiguration {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void test() throws Exception {
        mockMvc.perform(get("/test"))
               .andExpect(content().string("0 - not a test value"));
    }

}

这个测试也通过了,它使用了所有的实际配置,没有加载测试配置,所以所有的 bean 都是来自我们实际应用程序的 bean(就像它在容器中运行一样)。


@SpringBootTest
@AutoConfigureMockMvc
public class TestWithInnerTestConfiguration {

    @Configuration
    @Import(TestedApplication.class)
    static class InnerConfiguration {

        @Bean
        TestedServiceInterface service(MockedUtilInterface mockedUtil) {
            return () -> mockedUtil.value() + " - inner value";
        }

    }

    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private MockedUtilInterface mockedUtil;

    @Test
    void test() throws Exception {
        when(mockedUtil.value())
                .thenReturn(12345);

        mockMvc.perform(get("/test"))
               .andExpect(content().string("12345 - inner value"));
    }

}

这是一个内部类配置示例,它覆盖了一些 bean,使用了一些实际的 bean,还可以使用提供的 @MockBeans。


Here 你可以找到很多方法来配置 bean 以进行测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2018-02-21
    • 2021-12-23
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多