Bewusstssein发布的链接让我找到了jfcorugedo发布的可行答案。基本上,我要做的是在我的测试配置类中创建一个新的bean,该bean模拟Repository类,并用
我正在尝试测试一些具有方法级spring安全性的控制器,我想模拟控制器中的存储库依赖关系。基本上,我想测试(a)方法是否强制执行安全性,(b)在SpEL表达式中调用的其他bean是否工作。
我的问题是,当使用Mockito的@InjectMocks
来实例化控制器时,spring安全代理没有应用于控制器,并且绕过了方法安全性。如果我使用@Autowired
来允许Spring创建控制器,那么我的自定义方法级安全逻辑会被调用,但@Mock
对象不会被注入。
@RestController
@RequestMapping("/api/projects/{projectId}")
public class ProjectKeywordResource {
//I want to mock this repository
@Inject
private ProjectKeywordRepository projectKeywordRepository;
//Invokes another bean if user not assigned admin role.
@PreAuthorize("hasRole('ROLE_ADMIN')" + " or "
+ "@projectService.canEditProjectData(#projectId)")
@RequestMapping(value = "/projectKeywords", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<ProjectKeyword> create(
@PathVariable String projectId,
@RequestBody ProjectKeyword projectKeyword)
throws URISyntaxException {
projectKeywordRepository.save(projectKeyword);
return ResponseEntity.created(
new URI("/api/" + projectId + "projectKeywords/"
+ projectKeyword.getId())).body(result);
}
}
我的测试用例在这里:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class ProjectKeywordResourceSecurityTest {
private static final String DEFAULT_PROJECT_ID = "1";
@Mock
private ProjectKeywordRepository projectKeywordRepository;
//@Inject - Adding the following annotation adds the necessary spring security proxies,
but then ProjectKeywordResource uses the real ProjectKeywordRepository not the mock one.
@InjectMocks
private ProjectKeywordResource projectKeywordResource;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test(expected = AccessDeniedException.class)
@WithMockUser
@Transactional
public void testCreateThrowsAccessDenied() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
@Test
@WithMockUser(username = "admin", roles={"ADMIN"})
@Transactional
public void testCreateAuthorizationSuceedsForAdminUser() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
}
有没有一点配置魔法可以让我用必要的spring代理包装Mockito mock控制器,或者在测试用例中强制在注入的bean上使用mock?
@Primary
注释对其进行注释。添加Spring概要文件注释可以在默认情况下关闭这些bean,因此不会干扰其他测试。修订后的测试等级为:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@ActiveProfiles({"useMockRepositories","default"})
public class ProjectKeywordResourceSecurityTest {
private static final String DEFAULT_PROJECT_ID = "1";
@Inject
private ProjectKeywordResource projectKeywordResource;
@Test(expected = AccessDeniedException.class)
@WithMockUser
public void testCreateThrowsAccessDenied() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
@Test
@WithMockUser(username = "admin", roles={"ADMIN"})
public void testCreateAuthorizationSuceedsForAdminUser() throws Exception {
projectKeywordResource.create(DEFAULT_PROJECT_ID, createDefaultProjectKeyword());
}
我的测试配置类有以下内容:
@Configuration
public class TestConfiguration {
@Profile("useMockRepositories")
@Bean
@Primary
public ProjectKeywordRepository MockProjectKeywordRepository() {
return Mockito.mock(ProjectKeywordRepository.class);
}
}