[JAVA] MockMVC renvoie 200 même si je fais une demande vers un chemin qui n'existe pas

Environnement de vérification de fonctionnement

Situation où 200 est retourné

Tout d'abord, créez un simple Controller comme celui-ci: «TodoService» n'est pas important dans cet article, je vais donc l'omettre.

Controller.java


@RestController
@RequestMapping("todos") 
public class TodoRestController {
    @Inject
    TodoService todoService;
    @Inject
    Mapper beanMapper;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    public List<TodoResource> getTodos() {
        Collection<Todo> todos = todoService.findAll();
        List<TodoResource> todoResources = new ArrayList<>();
        for (Todo todo : todos) {
            todoResources.add(beanMapper.map(todo, TodoResource.class));
        }
        return todoResources;
    }
    
    @RequestMapping(method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    public TodoResource postTodos(@RequestBody @Validated TodoResource todoResource) {
        Todo createdTodo = todoService.create(beanMapper.map(todoResource, Todo.class));
        TodoResource createdTodoResponse = beanMapper.map(createdTodo, TodoResource.class);
        return createdTodoResponse;
    }
}

Écrivons un code de test pour Controller en utilisant MockMVC.

Test.java


@RunWith(SpringRunner.class)
@ContextHierarchy({@ContextConfiguration({"classpath:META-INF/spring/applicationContext.xml"}),
    @ContextConfiguration({"classpath:META-INF/spring/spring-mvc-rest.xml"})})
@WebAppConfiguration
public class TodoRestControllerTest {

  @Autowired
  WebApplicationContext webApplicationContext;

  MockMvc mockMvc;

  ObjectMapper mapper;

  @Before
  public void setup() {
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
        .addFilter(new XTrackMDCPutFilter(), "/**").alwaysDo(log()).build();
    mapper = new ObjectMapper();
  }
  @Test
  public void notExistPathTest() throws Exception {
    String title = "title";
    TodoResource todoRequest = new TodoResource();
    todoRequest.setTodoTitle(title);
    MvcResult result = mockMvc
        .perform(
            MockMvcRequestBuilders.post("/hage").content(mapper.writeValueAsString(todoRequest))
                .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isNotFound()).andReturn();
  }
}

Le chemin est / todos, donc si vous faites une demande à / hage, vous devriez obtenir 404, mais lorsque vous exécutez le test ...

java.lang.AssertionError: Status expected:<404> but was:<200>
	at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:54)
	at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:81)
	at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:665)
	at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
	at todo.api.TodoRestControllerTest.notExistPathTest(TodoRestControllerTest.java:75)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	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.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	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.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

Ce sera 200 pour une raison quelconque. : en pensant: En passant, si vous déployez sur le serveur AP et envoyez une requête à / hage, ce sera 404 comme prévu.

La cause est la fonction avant

Je n'ai pas du tout compris la cause, mais j'ai remarqué que j'avais défini <mvc: default-servlet-handler /> dans le spring-mvc-rest.xml chargé dans la classe de test. ..

Il s'agit d'un paramètre qui permet à la fonction de transférer la requête reçue par DispatcherServlet vers le servlet par défaut.

Autrement dit, si vous faites une demande vers un chemin qui n'existe pas, MockMVC la transmettra au servlet par défaut. Étant donné que la destination de transfert est sous la juridiction du serveur AP, ** MockMVC a renvoyé 200 car la transmission a réussi **. Donc, si vous supprimez <mvc: default-servlet-handler />, vous récupérerez 404.

Cependant, dans le cas d'applications d'écran qui ne sont pas l'API REST, si la fonction de transfert est désactivée, le fichier statique placé sur le serveur AP ne peut pas être référencé, le code d'état est donc 200 et transmet comme indiqué ci-dessous. Assurez-vous que la destination est le chemin par défaut.

    MvcResult result = mockMvc
        .perform(
            MockMvcRequestBuilders.post("/hage").content(mapper.writeValueAsString(todoRequest))
                .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk()).andExpect(forwardedUrl("default")).andReturn();
  }

c'est tout.

en conclusion

Pour le servlet par défaut, l'article Comprendre l'accès aux ressources statiques sur Spring MVC (+ Spring Boot) est facile à comprendre.

Recommended Posts

MockMVC renvoie 200 même si je fais une demande vers un chemin qui n'existe pas
Si hash [: a] [: b] [: c] = 0 dans Ruby, je veux que vous étendiez récursivement même si la clé n'existe pas
Comment faire fonctionner @Transactional qui ne fonctionne pas si vous ne l'utilisez pas correctement
Je veux FlashAttribute au printemps même si j'ai défini un proxy inverse! (ne pas faire)
Comment identifier le chemin sur lequel il est facile de se tromper
Une histoire que même un homme qui ne comprend pas le langage C pourrait ajouter de nouvelles fonctions à Ruby 2.6
Comment interagir avec un serveur qui ne plante pas l'application
J'ai essayé de créer une API Web qui se connecte à DB avec Quarkus
Une histoire qui a souffert d'un espace qui ne disparaît pas même s'il est taillé avec Java La cause est BOM
Une note que j'ai renoncé à essayer de créer une annotation personnalisée pour Lombok
[JPA] Comparez table1 et table2 pour obtenir et mettre à jour des données qui n'existent pas dans la table2.
Méthode de réglage qui ne change pas la taille même si le CSS est changé
Même en Java, je veux sortir vrai avec un == 1 && a == 2 && a == 3 (magie grise qui n'est pas tant que magie noire)
Je l'ai fait en Java pour toujours rendre (a == 1 && a == 2 && a == 3) vrai
Je voulais que (a == 1 && a == 2 && a == 3) vrai en Java
J'ai essayé de créer un nouvel algorithme de tri, mais je ne sais pas si c'est vraiment nouveau
[Java] Traitement de la situation où le programme qui écrit dans le flux de sortie du processus ne se termine pas même si waitFor
J'ai essayé de créer une fonction de connexion avec Java
[Java] J'ai essayé de créer un jeu Janken que les débutants peuvent exécuter sur la console
Ce n'est pas un gros problème si vous comprenez que j'étais accro à recevoir du courrier avec Java Mail depuis Exchange Online