简体   繁体   English

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

[英]Status 404 - MockMvc Authorization - Spring boot REST Docs

I have a controller 我有一个控制器

SmsMessageController.java 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;

}

and my test class SmsMessageControllerTest.java with MockMvc method: 我的测试类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"));
}

And my logs: 和我的日志:

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)

The problem is with authorization imho. 问题出在授权恕我直言。 In POSTMAN everything works well. 在POSTMAN中,一切正常。 Encoding in my method its ok because is the same in postman. 我的方法可以编码,因为邮递员是一样的。 Maybe somebody had problem like this? 也许有人有这样的问题?

PS I write simple client and works too, but i have to implement MockMvc with RESTdocs. PS我写了简单的客户端,也可以工作,但是我必须用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();
        }
    }
 @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"));
}

There are a couple of things wrong/flawed with this test. 此测试有几处错误/有缺陷的地方。

  1. Combining @SpringBootTest and a slice @WebMvcTest use either not both 结合使用@SpringBootTest和切片@WebMvcTest不能同时使用两者
  2. Running the test with MockitoJUnitRunner 使用MockitoJUnitRunner运行测试
  3. AutoConfigureMockMvc is implied by @WebMvcTest @WebMvcTest暗示AutoConfigureMockMvc
  4. @Autowirede on a static field will not work. static字段上的@Autowirede将不起作用。
  5. Manual setup of MockMvc then why use @WebMvcTest or @AutoConfigureMockMvc 手动设置MockMvc然后为什么使用@WebMvcTest@AutoConfigureMockMvc
  6. Use of @Mock instead of the Spring Boot managed @MockBean 使用@Mock代替Spring Boot管理的@MockBean

That being said your test should look something like this. 话虽这么说,您的测试应该看起来像这样。

@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"));
}

See also the Spring Boot Reference Guide section on autoconfigured Spring REST Docs as well as the section on Mocking Beans 另请参阅有关自动配置的Spring REST Docs的《 Spring Boot参考指南》部分以及有关“ 模拟Bean”的部分

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM