如何单元测试 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();
...
}
我正在尝试为其配置严重依赖环境变量的服务编写单元测试。 单元测试适用于服务层,但我 运行 在尝试为直接从环境变量读取地址的端点设置 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();
...
}