Home > Software engineering >  How to overwrite @WithMockUser set on class in a single test in spring boot
How to overwrite @WithMockUser set on class in a single test in spring boot

Time:10-12

If I have the annotation @WithMockUser on a test class in spring boot, how can I overwrite/null this setting for a single test in which I want to see how the code behaves without set principal?

CodePudding user response:

If you want to see how the code behaves with a different user, you can just put another @WithMockUser directly on the method.

@SpringBootTest
@WithMockUser(username="user", password="password")
public class UserSecurityTest {

  @Test
  @WithMockUser(username="otherUser", password="password")
  public void testMockUserOverride() {
    ...
  }
}

If you want to see how the code behaves with no credentials then you need to clear out the security context at the beginning of your test.

@SpringBootTest
@WithMockUser(username="user", password="password")
public class UserSecurityTest {
    @Test
    public void testNoAuth() {
        SecurityContextHolder.clearContext();
        ...
    }
}

Here is a complete example that includes a test that runs after clearing out the authentication to be sure it is restored to what the class-level mock is set to.

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.test.context.support.WithMockUser;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
@WithMockUser(username = "user", password = "password")
@TestMethodOrder(MethodOrderer.class)
public class SecurityTest {

    public String getCurrentUser() {
        return Optional.ofNullable(SecurityContextHolder.getContext())
              .map(SecurityContext::getAuthentication)
              .map(Authentication::getPrincipal)
              .map(user ->  ((User)user).getUsername())
              .orElse("noAuth");
    }

    @Test
    @Order(0)
    public void testClassLevelMockUser() {
        assertEquals("user",getCurrentUser());
    }

    @Test
    @Order(1)
    @WithMockUser(username = "otherUser")
    public void testOverrideMock() {
        assertEquals("otherUser", getCurrentUser());
    }

    @Test
    @Order(2)
    public void testNoAuth() {
        SecurityContextHolder.clearContext();
        assertEquals("noAuth", getCurrentUser());
    }

    @Test
    @Order(3)
    public void testClassLevelMockUserNotDestroyedByOtherTest() {
        assertEquals("user", getCurrentUser());
    }

}
  • Related