状态404 - MockMvc授权 - Spring启动REST文档

时间:2018-04-04 08:26:31

标签: java spring spring-mvc spring-boot mocking

我有一个控制器

SmsMessageController.java

@Slf4j
@RestController
@RequestMapping("/luxsms/message")
public class SmsMessageController {

private static final String STRING_REQUEST_ACCEPTED = " ";

private SmsStatusService smsStatusService;

private SmsMessageService smsMessageService;

private TaskExecutor taskExecutor;

private ApplicationContext context;

@Autowired
public SmsMessageController(SmsStatusService smsStatusService, SmsMessageService smsMessageService,
        TaskExecutor taskExecutor, ApplicationContext context) {
    this.smsStatusService = smsStatusService;
    this.smsMessageService = smsMessageService;
    this.taskExecutor = taskExecutor;
    this.context = context;
}

@GetMapping("/get/{id}")
public ResponseEntity<SmsMessageDto> get(@PathVariable("id") long id) {

    ResponseEntity<SmsMessageDto> toReturn = null;

    Optional<SmsMessage> byId = smsMessageService.findById(id);
    if (byId.isPresent()) {

        SmsMessageDto smsMessageDto = new SmsMessageDto(byId.get());
        toReturn = new ResponseEntity<>(smsMessageDto, HttpStatus.OK);

    } else {
        toReturn = new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
    return toReturn;

}

和我的测试类 SmsMessageControllerTest.java 使用MockMvc方法:

 @SpringBootTest
@AutoConfigureMockMvc
@RunWith(MockitoJUnitRunner.class)
@WebMvcTest(SmsMessageController.class)
public class SmsMessageControllerTest {

@Autowired
private static final String SERVER_URL = "http://localhost:5050";
private static final String PASSWORD = "pass";
private static final String LUXUSER = "user";
private static final String ROLES = "Admin";

private MockMvc mockMvc;

@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

@Mock
SmsMessageService smsMessageService;

@Before
public void before() throws IllegalAccessException {
    mockMvc = MockMvcBuilders.standaloneSetup(smsMessageService)
            .apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation))
            .build();
}

 @Test
 public void testShouldGetMessageWithIdNumberTwo() throws Exception {
            Base64.Encoder encoder = Base64.getEncoder();
            String encoding = encoder.encodeToString((LUXUSER + ":" + PASSWORD).getBytes());

    this.mockMvc.perform(MockMvcRequestBuilders.get("/luxsms/message/get/2").header("Authorization", "Basic " + encoding)
            .accept(MediaType.ALL))
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.content().string("{\"smsStatusId\": \"test\",\"receiver\": \"123456789\", \"databaseId\": 2}"))
            .andDo(MockMvcRestDocumentation.document("SmsMessageController/get"));
}

我的日志:

10:07:38.690 [main] DEBUG org.hibernate.validator.internal.engine.ValidatorFactoryImpl - HV000234: Using org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory as ValidatorFactory-scoped script evaluator factory.
10:07:38.743 [main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext@7a5ceedd
10:07:38.799 [main] DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Looking for exception mappings: org.springframework.test.web.servlet.setup.StubWebApplicationContext@7a5ceedd
10:07:38.855 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Initializing servlet ''
10:07:38.857 [main] INFO org.springframework.mock.web.MockServletContext - Initializing Spring FrameworkServlet ''
10:07:38.857 [main] INFO org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization started
10:07:38.860 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided
10:07:38.861 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using LocaleResolver [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver@63a5e46c]
10:07:38.861 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using ThemeResolver [org.springframework.web.servlet.theme.FixedThemeResolver@7e8e8651]
10:07:38.861 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using RequestToViewNameTranslator [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@49ef32e0]
10:07:38.861 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Using FlashMapManager [org.springframework.web.servlet.support.SessionFlashMapManager@271f18d3]
10:07:38.861 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Published WebApplicationContext of servlet '' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.]
10:07:38.861 [main] INFO org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization completed in 4 ms
10:07:38.861 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Servlet '' configured successfully
10:07:38.907 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - DispatcherServlet with name '' processing GET request for [/luxsms/message/get/2]
10:07:38.909 [main] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /luxsms/message/get/2
10:07:38.910 [main] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Did not find handler method for [/luxsms/message/get/2]
10:07:38.910 [main] WARN org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/luxsms/message/get/2] in DispatcherServlet with name ''
10:07:38.910 [main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - Successfully completed request

java.lang.AssertionError: Status 
Expected :200
Actual   :404
 <Click to see difference>


    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:55)
    at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:82)
    at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$matcher$9(StatusResultMatchers.java:617)
    at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:179)
    at pl.luxmed.luxsms.controller.SmsMessageControllerTest.testShouldGetMessageWithIdNumberOne(SmsMessageControllerTest.java:85)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.restdocs.JUnitRestDocumentation$1.evaluate(JUnitRestDocumentation.java:63)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
    at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

问题在于授权imho。在POSTMAN中,一切运作良好。编码在我的方法中它可以,因为在邮递员中是相同的。也许有人有这样的问题?

P.S我编写简单的客户端并且也可以工作,但我必须使用RESTdocs实现MockMvc。

@Test
    public void get(){
        String url = SERVER_URL + "/luxsms/message/get";

        ArrayList<String> ListOfId = new ArrayList<>();
        ListOfId.add(0, "/0");
        ListOfId.add(1, "/4");
        ListOfId.add(2, "/5");
        ListOfId.add(3, "/6");
        for (String param : ListOfId) {

            String urlWithParam = url + param;

            Base64.Encoder encoder = Base64.getEncoder();
            String encoding = encoder.encodeToString((LUXUSER + ":" + PASSWORD).getBytes());

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("Authorization", "Basic " + encoding);
            headers.add("Content-Type", "text/html");
            headers.add("charset", "utf-8");

            HttpEntity<String> entity = new HttpEntity<String>(" ", headers);

            StringHttpMessageConverter element =
                    new StringHttpMessageConverter(Charset.forName("UTF-8"));
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.getMessageConverters().add(0, element);

            ResponseEntity<String> exchange = restTemplate.exchange(urlWithParam, HttpMethod.GET, entity, String.class);

            System.out.println(exchange.getBody());
            System.out.println();
        }
    }

1 个答案:

答案 0 :(得分:1)

 @SpringBootTest
@AutoConfigureMockMvc
@RunWith(MockitoJUnitRunner.class)
@WebMvcTest(SmsMessageController.class)
public class SmsMessageControllerTest {

@Autowired
private static final String SERVER_URL = "http://localhost:5050";
private static final String PASSWORD = "pass";
private static final String LUXUSER = "user";
private static final String ROLES = "Admin";

private MockMvc mockMvc;

@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

@Mock
SmsMessageService smsMessageService;

@Before
public void before() throws IllegalAccessException {
    mockMvc = MockMvcBuilders.standaloneSetup(smsMessageService)
            .apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation))
            .build();
}

 @Test
 public void testShouldGetMessageWithIdNumberTwo() throws Exception {
            Base64.Encoder encoder = Base64.getEncoder();
            String encoding = encoder.encodeToString((LUXUSER + ":" + PASSWORD).getBytes());

    this.mockMvc.perform(MockMvcRequestBuilders.get("/luxsms/message/get/2").header("Authorization", "Basic " + encoding)
            .accept(MediaType.ALL))
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.content().string("{\"smsStatusId\": \"test\",\"receiver\": \"123456789\", \"databaseId\": 2}"))
            .andDo(MockMvcRestDocumentation.document("SmsMessageController/get"));
}

这项测试存在一些错误/缺陷。

  1. 合并@SpringBootTest和切片@WebMvcTest使用其中之一
  2. 使用MockitoJUnitRunner
  3. 运行测试 {li> AutoConfigureMockMvc@WebMvcTest 隐含 @Autowirede字段上的
  4. static将无效。
  5. 手动设置MockMvc,然后使用@WebMvcTest@AutoConfigureMockMvc
  6. 使用@Mock代替Spring Boot托管@MockBean
  7. 据说你的测试看起来应该是这样的。

    @RunWith(SpringRunner)
    @WebMvcTest(SmsMessageController.class)
    @AutoConfigureRestDocs
    public class SmsMessageControllerTest {
    
      private static final String PASSWORD = "pass";
      private static final String LUXUSER = "user";
      private static final String ROLES = "Admin";
    
      @Autowired
      private MockMvc mockMvc;
    
      @MockBean
      private SmsMessageService smsMessageService;
    
       @Test
       public void testShouldGetMessageWithIdNumberTwo() throws Exception {
           Base64.Encoder encoder = Base64.getEncoder();
           String encoding = encoder.encodeToString((LUXUSER + ":" + PASSWORD).getBytes());
    
        this.mockMvc.perform(MockMvcRequestBuilders.get("/luxsms/message/get/2").header("Authorization", "Basic " + encoding)
                .accept(MediaType.ALL))
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.content().string("{\"smsStatusId\": \"test\",\"receiver\": \"123456789\", \"databaseId\": 2}"))
                .andDo(MockMvcRestDocumentation.document("SmsMessageController/get"));
    }
    

    另请参阅autoconfigured Spring REST Docs上的“Spring Boot参考指南”部分以及Mocking Beans

    部分