【问题标题】:No mapping for request with mockmvc没有使用 mockmvc 的请求映射
【发布时间】:2020-11-24 19:14:33
【问题描述】:

当我使用以下控制器/测试配置收到“请求的映射错误”时,目前正在努力解决问题。 控制器:

@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
public class AdtechController {

private final AdtechService adtechService;

@PostMapping(value = "/subscriber/session")
public ResponseEntity<ResponseDto> submitSession(@RequestBody RequestDto requestDto) {
    log.trace("execute submitSession with {}", requestDto);
    ResponseDtoresponse = adtechService.submitSession(requestDto);
    return new ResponseEntity<>(response, HttpStatus.OK);
}

@ExceptionHandler(AdtechServiceException.class)
public ResponseEntity<AdtechErrorResponse> handleAdtechServiceException(AdtechServiceException e) {
    return new ResponseEntity<>(new AdtechErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
}

}

测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@SpringJUnitConfig({AdtechTestConfig.class})
public class AdtechControllerTest {

private static final ObjectMapper OBJECT_MAPPER = JsonUtil.getJackson();

@Autowired
private MockMvc mockMvc;

@Test
public void testSubmitSession() throws Exception {
    RequestDto requestDto = new RequestDto ();
    requestDto.setKyivstarId("1123134");
    requestDto.setMsisdn("123476345242");
    requestDto.setPartnerId("112432523");
    requestDto.setPartnerName("125798756");
    String request = OBJECT_MAPPER.writeValueAsString(requestDto);
    System.out.println("REQUEST: " + request);
    String response = OBJECT_MAPPER.writeValueAsString(new ResponseDto("123"));
    System.out.println("RESPONSE: " + response);
    mockMvc.perform(post("/subscriber/session")
            .content(MediaType.APPLICATION_JSON_VALUE)
            .content(request))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(content().string(containsString(response)));

}

}

配置:

@Configuration
public class AdtechTestConfig {

@Bean
public AdtechService adtechTestService() {
    return requestDto -> new AdtechResponseDto("123");
}

}

测试执行后,我得到 没有 POST /subscriber/session 的映射

挣扎的原因是我来自其他具有相同配置的模块的代码工作正常。有人能指出我错过了什么吗?提前致谢!

【问题讨论】:

  • 对于初学者来说,请自行决定要使用什么,Junit4 或 Junit5。目前你似乎正在混合两者。
  • @M.Deinum 你的意思是这部分:@RunWith(SpringRunner.class) ?我已经删除了它,现在它看起来像这样: SpringBootTest AutoConfigureMockMvc Sp​​ringJUnitConfig({AdtechTestConfig.class}) 仍然失败并出现同样的错误
  • 您使用的是哪个@Test 注释?同时删除你想使用的@SpringJUnitConfig @SpringBootTest 然后不要使用这个注解。
  • @M.Deinum 我正在使用 org.junit.jupiter.api.Test
  • 所以您现在使用的是 JUnit5。该配置覆盖了 Spring Boot 测试,我怀疑您的测试配置(为什么需要它?)只是实际需要加载的版本的一半。所以删除它,你应该有@SpringBootTest,这就足够了。

标签: java spring spring-boot mockito mockmvc


【解决方案1】:

试试这个:

@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
public class AdtechController {

private AdtechService adtechService;

public AdtechController (AdtechService adtechService) {
        this.adtechService= adtechService;
}

@PostMapping(value = "/subscriber/session")
public ResponseEntity<ResponseDto> submitSession(@RequestBody RequestDto requestDto) {
    log.trace("execute submitSession with {}", requestDto);
    ResponseDtoresponse = adtechService.submitSession(requestDto);
    return new ResponseEntity<>(response, HttpStatus.OK);
}

@ExceptionHandler(AdtechServiceException.class)
public ResponseEntity<AdtechErrorResponse> handleAdtechServiceException(AdtechServiceException e) {
    return new ResponseEntity<>(new AdtechErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
}

}

测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@SpringJUnitConfig({AdtechTestConfig.class})
public class AdtechControllerTest {

private static final ObjectMapper OBJECT_MAPPER = JsonUtil.getJackson();

@Autowired
private MockMvc mockMvc;
@Autowired
private AdtechService adtechService;

@Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        this.mvc = MockMvcBuilders.standaloneSetup(new AdtechController(adtechService)).build();
}

@Test
public void testSubmitSession() throws Exception {
    RequestDto requestDto = new RequestDto ();
    requestDto.setKyivstarId("1123134");
    requestDto.setMsisdn("123476345242");
    requestDto.setPartnerId("112432523");
    requestDto.setPartnerName("125798756");
    String request = OBJECT_MAPPER.writeValueAsString(requestDto);
    System.out.println("REQUEST: " + request);
    String response = OBJECT_MAPPER.writeValueAsString(new ResponseDto("123"));
    System.out.println("RESPONSE: " + response);
    mockMvc.perform(post("/subscriber/session")
            .content(MediaType.APPLICATION_JSON_VALUE)
            .content(request))
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(content().string(containsString(response)));

}

}

【讨论】:

  • 首先感谢您的回答。它不起作用,同样的问题。
【解决方案2】:

AdtechTestConfig.class 是否将 /ad-tech 路径段引入到您的测试请求中?如果是这样,这就是您的测试尝试路径 /ad-tech/subscriber/session 而不是 /subscriber/session 的原因。

如果这实际上是正确的 uri,那么您可以将 @RequestMapping 添加到控制器,如下所示,或者只是添加到 post 方法本身

@Slf4j
@Validated
@RestController
@RequestMapping("/ad-tech")
@RequiredArgsConstructor
public class AdtechController {

private final AdtechService adtechService;

@PostMapping(value = "/subscriber/session")
public ResponseEntity<ResponseDto> submitSession(@RequestBody RequestDto requestDto) {
...

【讨论】:

  • 更新了我的问题。配置类只是模拟服务类。
  • 在这种情况下,我会建议下面@M.Deinum 的答案
【解决方案3】:

显然你正在加载一个配置类来模拟 bean,这会干扰 Spring Boot 的其他部分,并可能导致部分加载你的应用程序。我怀疑只有模拟服务可用。

使用@MockBean 代替测试配置为服务创建模拟并在其上注册行为。

@SpringBootTest
@AutoConfigureMockMvc
public class AdtechControllerTest {

  private static final ObjectMapper OBJECT_MAPPER = JsonUtil.getJackson();

  @Autowired
  private MockMvc mockMvc;
  @MockBean
  private AdtechService mockService;

  @BeforeEach
  public void setUp() {
    when(mockService.yourMethod(any()).thenReturn(new AdtechResponseDto("123")); 
  }


  @Test
  public void testSubmitSession() throws Exception {
    // Your original test method
  }
}

如果您只想测试您的控制器,您可能还需要考虑使用@WebMvcTest 而不是@SpringBootTest

@WebMvcTest(AdTechController.class)
public class AdtechControllerTest {

  private static final ObjectMapper OBJECT_MAPPER = JsonUtil.getJackson();

  @Autowired
  private MockMvc mockMvc;
  @MockBean
  private AdtechService mockService;

  @BeforeEach
  public void setUp() {
    when(mockService.yourMethod(any()).thenReturn(new AdtechResponseDto("123")); 
  }


  @Test
  public void testSubmitSession() throws Exception {
    // Your original test method
  }
}

这将加载一个缩小版本的上下文(仅 Web 部件)并且运行速度会更快。

【讨论】:

  • 非常感谢,您对使用 WebMvcTest(AdTechController.class) 的建议确实成功了!
猜你喜欢
  • 2014-02-06
  • 2018-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多