【发布时间】:2017-05-26 05:41:24
【问题描述】:
我正在制作一个休息 api。最近,我在项目中添加了 Basic Auth 并指定了如下配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public final static String ROLE_ADMIN = "ADMIN";
public final static String ROLE_USER = "USER";
/**
* Determines the resource access for different account types
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/create").permitAll()
.antMatchers("/admin/**").hasRole(ROLE_ADMIN)
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(inMemoryUserDetailsManager());
}
/**
* Initially fills Spring Security with default accounts
*/
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
final Properties users = new Properties();
users.put("user","pass,ROLE_USER,enabled"); //login = user, password = pass
users.put("admin","pass,ROLE_ADMIN,enabled"); //login = admin, password = pass
return new InMemoryUserDetailsManager(users);
}
}
我还为它们制作了一些控制器和一些测试:
控制器:
@RestController
public class MovieController {
@Autowired @Qualifier("MovieService")//not relevant
private MovieService ms;
@Autowired @Qualifier("CastService")//not relevant
private CastService cs;
@RequestMapping(value = "admin/movies", method = GET)
public List<Movie> selectAllMovies(){
return ms.selectAll();
}
//the rest of the code..
}
和测试:
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class MovieControllerTest {
@Mock
private MovieService movieService;
@Mock
private CastService castService;
@Mock
private ActorService actorService;
@Mock
private UserService userService;
@InjectMocks
private MovieController movieController;
private MockMvc mvc;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(movieController).build();
}
@Test
@WithMockUser(roles = "ADMIN", username = "admin", password = "pass")
@WithUserDetails("admin")
public void testGetAllMovies() throws Exception {
List<Movie> movieList = Arrays.asList(
new Movie("title1", "desc1", MovieType.newest, 10f, true),
new Movie("title2", "desc2", MovieType.newest, 10f, true),
new Movie("title3", "desc3", MovieType.newest, 10f, true));
when(movieService.selectAll()).thenReturn(movieList);
String uri = "admin/movies";
MvcResult result = mvc.perform(MockMvcRequestBuilders.get(uri)
.accept(MediaType.APPLICATION_JSON)).andReturn();
String content = result.getResponse().getContentAsString();
int status = result.getResponse().getStatus();
verify(movieService, times(1)).selectAll();
Assert.assertEquals("failure - expected HTTP status 200", 200, status);
Assert.assertTrue("failure - expected HTTP response body to have a value", content.trim().length() > 0);
}
//the rest of the code..
}
但是当我运行测试时,我从 Mockito 收到错误消息:
Wanted but not invoked:
movieService.selectAll();
-> at com.myproject.Controller.MovieControllerTest.testGetAllMovies(MovieControllerTest.java:87)
Actually, there were zero interactions with this mock.
看来,Spring 安全性不允许测试调用需要身份验证的 url(“admin/movies”)。正如在配置文件中指定的那样,此 url 需要 ADMIN 角色。有趣的是,当我在控制器和测试中删除 url 的“admin”部分时,测试有效!但是,根据配置,它仍然需要使用 USER 角色进行身份验证(只有“/user/create”不需要它,正如您在配置中看到的那样)。
我尝试过使用@WithMockUser(username="admin", password="pass", roles="ADMIN"),但它没有帮助,错误保持不变。
【问题讨论】:
标签: spring security testing mocking role