我在使用Spring Security(使用Spring Boot 1.3.1.RELEASE)和Mockito时遇到了相当大的问题。
当我在SampleService类的方法@PreAuthorize
上使用doIt()
时,Mockito在测试getValue()
期间没有在SampleService内部模拟方法doItTest()
(在SampleDao类中声明)
结果是:java.lang.AssertionError: expected:<false> but was:<true>
它的发生是因为指令
Mockito.when(dao.getValue()).thenReturn(ctrl);
当我在SampleService类的方法doIt()上使用@PreAuthorize时,不起作用。
当我从方法@PreAuthorize
中移除doIt()
时,测试doItTest()
正常工作(Mockito正在嘲笑getValue()
)。
但是当我在方法doItDeniedTest()
上使用@PreAuthorize
运行其他测试doIt()
时,其工作正常,因为@PreAuthorize
会抛出AccessDeniedException。
我该如何解决?
谢谢大家。
代码:
@SpringBootApplication
public class AppApplication {
public static void main(String[] args) {
SpringApplication.run(AppApplication.class, args);
}
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private LogoutHandler logoutHandler;
@Autowired
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private AccessDeniedHandler accessDeniedHandler;
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/error/**").permitAll()
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/adm/**").hasAnyRole(Role.ROOT,Role.ADM)
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler)
.defaultSuccessUrl("/home",true)
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login")
.permitAll()
.addLogoutHandler(logoutHandler)
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
}
}
@Repository
public class SampleDao implements Dao {
@Override
public boolean getValue(){
return true;
}
}
@Service
public class SampleService implements Service{
@Autowired
private Dao dao;
@Override
@PreAuthorize(value="hasRole('USR')")
public boolean doIt(){
return dao.getValue();
}
}
我的测试课程是:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {AppApplication.class})
@WebAppConfiguration
public class SampleServiceImplTest {
@Mock
private SampleDaoImpl dao;
@Autowired
@Qualifier("sampleServiceImpl")
@InjectMocks
private SampleService svc;
@Before
public void initMocks(){
MockitoAnnotations.initMocks(this);
}
@Test(expected=AccessDeniedException.class)
@WithMockUser(username="usr",roles={"ROOT"})
public void doItDeniedTest() {
svc.doIt();
}
@Test
@WithMockUser(username="usr",roles={"USR"})
public void doItTest() {
Boolean ctrl = Boolean.FALSE;
Mockito.when(dao.getValue()).thenReturn(ctrl);
Boolean rt = svc.doIt();
assertEquals(ctrl,rt);
}
}
答案 0 :(得分:3)
您正在将集成测试与单元测试相结合。不要那样做。 您有两种选择:
答案 1 :(得分:1)
阅读blog后,我改变了我的测试类。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {AppApplication.class,TestConfiguration.class})
@WebAppConfiguration
public class SampleServiceImplTest {
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class TestConfiguration {
@Bean
@Primary
public SampleDaoImpl gatSampleDaoImpl(){
return Mockito.mock(SampleDaoImpl.class);
}
}
@Autowired
private SampleDaoImpl dao;
@Autowired
private SampleService svc;
@Before
public void initMocks(){
MockitoAnnotations.initMocks(this);
}
@Test(expected=AccessDeniedException.class)
@WithMockUser(username="usr",roles={"ROOT"})
public void doItDeniedTest() {
svc.doIt();
}
@Test
@WithMockUser(username="usr",roles={"USR"})
public void doItTest() {
Boolean ctrl = Boolean.FALSE;
Mockito.when(dao.getValue()).thenReturn(ctrl);
Boolean rt = svc.doIt();
assertEquals(ctrl,rt);
}
}