Reputation: 1163
I'm trying to write Unit tests for a service that relies heavily on environment variables for its configuration. Unit tests work fine for the service layer but I'm running into problems trying to set up MockMVC tests for the endpoints that read their addresses directly from environment variables.
I tried to set the variable directly in the test but I assume that it would require the application context to populate the controller side value and I'm trying to avoid that for simple unit tests.
Using: Java11, Mockito2, JUnit5, SpringBoot2.2.0.M6
Controller:
@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);
}
}
Test where I manually generate the MockMVC BeforeEach test:
@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());
}
The received error is:
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}"
Upvotes: 0
Views: 945
Reputation: 3572
In a standalone setup there is no support for placeholder values embedded in request mappings. So you should use StandaloneMockMvcBuilder.addPlaceholderValue(...)
:
@BeforeEach
void beforeEach() throws JsonProcessingException {
mockMvc = MockMvcBuilders.standaloneSetup(outgoingMessageAPI)
.addPlaceholderValue("MQTT_CLIENT_API_OUTGOING_MESSAGE", "/endpoint")
.build();
...
}
Upvotes: 2