如何单元测试 Spring-使用 MockMVC 引导 REST 端点,其中路径映射是环境变量?

How to Unit test Spring-Boot REST endpoints with MockMVC where the path mappings are environment variables?

我正在尝试为其配置严重依赖环境变量的服务编写单元测试。 单元测试适用于服务层,但我 运行 在尝试为直接从环境变量读取地址的端点设置 MockMVC 测试时遇到问题。

我试图在测试中直接设置变量,但我假设它需要应用程序上下文来填充控制器端的值,而我正试图在简单的单元测试中避免这种情况。

使用:Java11、Mockito2、JUnit5、SpringBoot2.2.0.M6

控制器:

@RestController
public class OutgoingMessageAPI {

    private MessagingService service;

    public OutgoingMessageAPI(MessagingService service) {
        this.service = service;
    }

    @PostMapping("${MQTT_CLIENT_API_OUTGOING_MESSAGE}")
    public ResponseEntity postMessage(@RequestBody @Valid Message message) {
         service.handleOutgoingMessage(message);
    }

}

在我手动生成 MockMVC BeforeEach 测试的地方进行测试:

@ExtendWith(MockitoExtension.class)
@DisplayName("Outgoing Message API Test")
class OutgoingMessageAPITest {

    private MockMvc mockMvc;

    @Mock
    private ObjectMapper objectMapper;

    @Mock
    private MessagingService messagingService;

    @InjectMocks
    private OutgoingMessageAPI outgoingMessageAPI;

    private Message validIncomingMessage;
    private String validIncomingMessageJSON;

    @BeforeEach
    void beforeEach() throws JsonProcessingException {
        mockMvc = MockMvcBuilders.standaloneSetup(outgoingMessageAPI).build();

        validIncomingMessage = new Message());
        validIncomingMessageJSON = new ObjectMapper().writeValueAsString(validIncomingMessage);
    }

    @Test
    @DisplayName("A valid message is posted")
    void postMessageValid() throws Exception {
        var endpoint = "/endpoint";
        System.setProperty("MQTT_CLIENT_API_OUTGOING_MESSAGE", endpoint);
        mockMvc.perform(post(endpoint)
                    .content(validIncomingMessageJSON)
                    .contentType("application/json"))
                .andExpect(status().isAccepted());
    }

收到的错误是:

    Invalid mapping on handler class [com.tlvlp.iot.server.mqtt.client.rpc.OutgoingMessageAPI]: public org.springframework.http.ResponseEntity com.tlvlp.iot.server.mqtt.client.rpc.OutgoingMessageAPI.postMessage(com.tlvlp.iot.server.mqtt.client.persistence.Message)
    Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'MQTT_CLIENT_API_OUTGOING_MESSAGE' in value "${MQTT_CLIENT_API_OUTGOING_MESSAGE}"

在独立设置中,不支持请求映射中嵌入的占位符值。所以你应该使用 StandaloneMockMvcBuilder.addPlaceholderValue(...):

@BeforeEach
void beforeEach() throws JsonProcessingException {
    mockMvc = MockMvcBuilders.standaloneSetup(outgoingMessageAPI)
            .addPlaceholderValue("MQTT_CLIENT_API_OUTGOING_MESSAGE", "/endpoint")
            .build();
    ...
}