Search code examples
javaspring-mvcspring-boothtmlunitspring-mvc-test

405 Request method 'POST' not supported when testing spring application


I prepared and extended this existing spring example which is running fine. You can simply login with "user" and "password" and afterwards you get forwarded to user/index.

Using this controller

@Controller
public class LoginController {
    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @GetMapping("/login-error")
    public String loginError(Model model) {
        model.addAttribute("loginError", true);
        return "login";
    }
}

But as soon i run the example test which is using WebClient the same login is causing the exception:

com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException: 405 Request method 'POST' not supported for http://localhost:8080/login

which is strange because the application itself works just fine.

EDIT: This is the test method causing the problem

@And("^the user clicks the login button$")
public void theUserClicksTheLoginButton() throws IOException {
    page = page.getElementById("login").click();
}

I didn't expect that the click method of WebClient is using POST instead of realy executing the input field in the html.

<form th:action="@{/login}" method="post">
    <label for="username">Username</label>:
    <input type="text" id="username" name="username" autofocus="autofocus" /> <br />
    <label for="password">Password</label>:
    <input type="password" id="password" name="password" /> <br />
    <input type="submit" id="login" value="Log in" />
</form>

EDIT 2: Ok maybee i schould claryfy my question a bit. I know a login should done over POST, and my @Controller is only providing @GetMapping but this is ok because spring security is handling the POST requests as i can see in the header while login in:

enter image description here

My question is why is it working fine while running the app, and why hasn't it the same behavior when using WebClient.


Solution

  • I'm not very familiar with setting up Spring with Cucumber, and I'm not sure about mixing both SpringRunner and Cucumber runners in the same setup.

    I've updated your test setup like this:

    @RunWith(SpringRunner.class)
    @WebMvcTest
    @ContextConfiguration
    @Import(SecurityConfig.class)
    public class LoginFeatureStepDefinition {
        private String username;
        private String password;
        private HtmlPage page;
    
        @Autowired
        private WebClient webDriver;
    
    1. I've replaced @SpringBootTest with @WebMvcTest, as the mockmvc auto-configuration will take care of the webclient setup for you. If you wanted to start an actual server with the whole application and test it with an HTTP client, you need to setup @SpringBootTest in a different way.
    2. In a MockMvc setup, the security configuration is not imported by default, so you need to import it