Getting REST version from request mapping of controller for mockmvc

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();
    }
}

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

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];