Enterprise Java

Testing Conditional Links with @WithMockUser in Spring Security

Hypermedia APIs provide not just data but also actions that users can take, often exposed as conditional links or affordances. In Spring applications secured by Spring Security, it’s common to tailor these hypermedia controls based on the currently authenticated user’s role or privileges.

To ensure this dynamic behavior works correctly, especially in testing, Spring offers the powerful @WithMockUser annotation. It allows you to simulate authenticated requests and validate which hypermedia links are shown or hidden based on roles.

Let’s walk through how to test conditional links using @WithMockUser and Spring HATEOAS.

Why Conditional Links Matter

In hypermedia-driven REST APIs, links such as “update”, “delete”, or “admin” should be shown only to users with the appropriate authority.

For example, only an admin might see:

"_links": {
  "delete": {
    "href": "/users/5"
  }
}

Whereas a regular user should not see that link.

Setup: Controller with Conditional Links

Here’s a controller that adds links based on user roles:

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public EntityModel<User> getUser(@PathVariable Long id, Authentication auth) {
        User user = userService.findById(id);

        EntityModel<User> model = EntityModel.of(user);
        model.add(linkTo(methodOn(UserController.class).getUser(id)).withSelfRel());

        if (auth != null && auth.getAuthorities().stream()
                .anyMatch(granted -> granted.getAuthority().equals("ROLE_ADMIN"))) {
            model.add(linkTo(methodOn(UserController.class).deleteUser(id)).withRel("delete"));
        }

        return model;
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

Writing Tests with @WithMockUser

To validate whether the correct links appear for different roles, use @WebMvcTest combined with @WithMockUser.

✅ Test: Admin User Sees the Delete Link

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    @WithMockUser(username = "admin", roles = {"ADMIN"})
    void adminShouldSeeDeleteLink() throws Exception {
        User user = new User(5L, "Alice");
        given(userService.findById(5L)).willReturn(user);

        mockMvc.perform(get("/users/5"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$._links.delete.href").value("http://localhost/users/5"));
    }
}

❌ Test: Regular User Should NOT See the Delete Link

@Test
@WithMockUser(username = "bob", roles = {"USER"})
void userShouldNotSeeDeleteLink() throws Exception {
    User user = new User(5L, "Alice");
    given(userService.findById(5L)).willReturn(user);

    mockMvc.perform(get("/users/5"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$._links.delete").doesNotExist());
}

Tips and Best Practices

  • Always test both inclusion and exclusion of conditional links to cover security boundaries.
  • Use @WithMockUser to quickly simulate users without needing full authentication setup.
  • For more complex setups, use SecurityMockMvcRequestPostProcessors.jwt() if you’re working with OAuth2/JWT-based security.
  • If your logic checks for custom claims or attributes, consider using @WithSecurityContext.

Summary

Conditional links are essential to secure, self-describing hypermedia APIs. Spring makes it easy to expose links based on roles and just as easy to test that logic using @WithMockUser. By simulating different user roles in tests, you can ensure your API behaves securely and predictably across a variety of access levels.

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button