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