I am using:
request.IsUserInRole("ADMIN")
in one of my controllers to determine the response to the request. I tried to mock the request in my test like:
@Mock
private HttpServletRequest httpRequest;
and to use Springs annotation @WithMockUser
:
@Test
@WithMockUser(roles={"USER, ADMIN"})
public void getAccountsTest() throws Exception {...}
Both didn't work.
Question 1: How can I mock request.IsUserInRole("ADMIN")
in a JUnit test?
Question 2: What influence does @WithMockUser
have on the request and request.IsUserInRole("ADMIN")
?
Thanks and best regards
---- edit ----
"Didn't work" means I have a test method:
@Test
@WithMockUser(username = "user", roles={"USER"})
public void getAccountsReturnForbiddenTest() throws Exception {
mockMvc.perform(get("/accounts/"))
.andExpect(status().isForbidden());
}
which should return 403, not allowed because of the controller:
@RequestMapping(method=RequestMethod.GET)
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<PagedResources<AccountResource>> getAccounts(...){...}
But the request returns 200, OK.
And I am using Spring Boot 1.4.1.
---- edit 2 ----
My JUnit Test-class:
@Transactional
@ContextConfiguration
public class AccountControllerTestDoc extends AbstractControllerTest {
@InjectMocks
private AccountController accountController;
@Mock
private AccountService accountService;
private String uriBase = "";
@Before
public void setup() {
// Initialize Mockito annotated components
MockitoAnnotations.initMocks(this);
// Prepare the Spring MVC Mock components for standalone testing
setup(accountController);
}
@Test
@WithMockUser(username = "user", roles={"USER"})
public void getAccountsReturnForbiddenTest() throws Exception {
String uri = uriBase + "/accounts";
mockMvc.perform(get(uri))
.andExpect(status().isForbidden());
}
}
with AbstractControllerTest:
@WebAppConfiguration
public abstract class AbstractControllerTest extends AbstractTest {
protected MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
protected void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
protected void setup(BaseController controller) {
mockMvc = MockMvcBuilders.standaloneSetup(controller))
.build();
}
}
and AbstractTest:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public abstract class AbstractTest {
protected Logger LOG = LoggerFactory.getLogger(this.getClass());
}
---- solution ----
MockMvc
standaloneSetup
isn't aware of the web application context and therefore not aware of the security filter chain. One has to setup MockMvc
with the web application context and the security filter chain to be able to test security aspects.
Here is my now working solution, I edited the AbstractControllerTest:
@WebAppConfiguration
public abstract class AbstractControllerTest extends AbstractTest {
protected MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
@Autowired
FilterChainProxy springSecurityFilterChain;
protected void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(wac)
.addFilters(springSecurityFilterChain)
.build();
}
protected void setup(BaseController controller) {
mockMvc = MockMvcBuilders.standaloneSetup(controller))
.build();
}
}