Skip to content

Instantly share code, notes, and snippets.

@mike-seger
Last active November 4, 2024 15:50
Show Gist options
  • Save mike-seger/1cfc0907baa1729136ec7e39f6abc417 to your computer and use it in GitHub Desktop.
Save mike-seger/1cfc0907baa1729136ec7e39f6abc417 to your computer and use it in GitHub Desktop.

You:

in Spring i can do tests @WithMockUser and a list of roles is there a way to achieve the same with parameterized tests looping through an actual list of roles instead of a single test with the combination of roles?

ChatGPT:

Yes, you can achieve this with parameterized tests by dynamically setting up each test with a single role from a list of roles. However, @WithMockUser doesn’t directly support parameterized roles out of the box. Instead, you can use @ParameterizedTest and programmatically create a mock user with each role in the list.Here’s how you can do it by leveraging SecurityContextHolder to manually set up the authentication for each test:

import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.MethodSource
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.security.authentication.TestingAuthenticationToken
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.get
import java.util.stream.Stream

@SpringBootTest
@AutoConfigureMockMvc
class YourControllerTests(@Autowired val mvc: MockMvc) {

    @ParameterizedTest
    @ValueSource(strings = ["ROLE_USER", "ROLE_ADMIN", "ROLE_GUEST"])
    @DisplayName("Test with different roles")
    fun `test with various roles`(role: String) {
        mvc.perform {
            get("/path/resource") {
                with(SecurityMockMvcRequestPostProcessors.user("testUser").roles(role))
                accept(MediaType.APPLICATION_JSON)
            }
        }
        .andDo { print() }
        .andExpect {
            // Your assertions here, e.g., status { isOk() }
        }
    }
}

Explanation

  1. Set Security Context : Inside each test, manually set up the SecurityContextHolder with a mock authentication containing the current role.

  2. Clear Security Context : Use @AfterEach to clear the security context after each test.

This approach allows you to test each role individually in a parameterized fashion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment