Mockito模拟并确保测试方法级别的弹簧安全性



我正在尝试测试一些具有方法级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?

Bewusstssein发布的链接让我找到了jfcorugedo发布的可行答案。基本上,我要做的是在我的测试配置类中创建一个新的bean,该bean模拟Repository类,并用@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);
    }
}

相关内容

  • 没有找到相关文章

最新更新