Getting REST version from request mapping of controller for mockmvc

özkan pakdil - Sep 12 '23 - - Dev Community

When we write a spring rest controller we give version url and start writing different functions as endpoints like below

@RestController
@RequestMapping("/api/v1")
public class ControllerApi {

    final LoginSender loginSender;

    public ControllerApi(LoginSender loginSender) {
        this.loginSender = loginSender;
    }

    @PostMapping("/login")
    boolean login(@RequestBody LoginParams params) {
        return loginSender.login(params.server(), params.login(), params.password(), params.build(), params.webManager());
    }

    @GetMapping("/get1")
    LoginParams get1(@RequestParam String login, @RequestParam(required = false) String webMan,
                     @RequestParam(required = false) String server, @RequestParam(required = false) String pass,
                     @RequestParam(required = false) String build) {
        return LoginParams.builder()
                .webManager(webMan)
                .server(server)
                .password(pass)
                .login(login)
                .build(build)
                .build();
    }
}

Enter fullscreen mode Exit fullscreen mode

ib the future this controller will have different version number from v1 to v2 or in the future someone will change login endpoint from “/login” to “/loginJwt” but function order probably will not change. So in order to prevent your tests to fail we can collect these data from controller class like the code below.

@BeforeEach
void beforeEach() throws NoSuchMethodException {
    RequestMapping requestMapping = ControllerApi.class.getAnnotation(RequestMapping.class);
    Method[] methods = ControllerApi.class.getDeclaredMethods();
    loginUrl = methods[0].getAnnotation(PostMapping.class).value()[0];
    get1Url = methods[1].getAnnotation(GetMapping.class).value()[0];
    apiVersion = requestMapping.value()[0];
}
@Test
void login() throws Exception {
    when(loginSender.login(any(), any(), any(), any(), any())).thenReturn(true);

    String mvcResult = mockMvc.perform(post(apiVersion + loginUrl)
                    .content(mapper.writeValueAsString(LoginParams.builder().build()))
                    .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andReturn().getResponse().getContentAsString();
    Assertions.assertEquals("true", mvcResult);
}

Enter fullscreen mode Exit fullscreen mode

One way to write more independent tests. You can see running code here

or another way to get the methods by name, like below

loginUrl = Arrays.stream(methods)
        .filter(f->f.getName().toLowerCase().contains("login"))
        .findFirst()
        .get()
        .getAnnotation(PostMapping.class).value()[0];
get1Url = Arrays.stream(methods)
        .filter(f->f.getName().toLowerCase().contains("get1"))
        .findFirst()
        .get()
        .getAnnotation(GetMapping.class).value()[0];

Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player