0

我有一个使用 Spring Boot 1.5.21 编写的库模块。

该库有一个@Service带有注释的方法,@PreAutorize仅允许具有ADMIN权限的用户执行某些操作,例如delete

然后我有一个使用该库的 Spring Boot 应用程序。如果我运行该应用程序并手动测试它,它就可以工作。只有管​​理员可以删除。我想为它写测试。

我正在考虑为模块和主应用程序编写单独的测试。在我的模块中,我可以成功地对操作进行单元测试。但是我在测试时遇到了麻烦@PreAuthotize,因为模块中不存在安全上下文,而是在主应用程序中。有没有办法在模块中测试该注释,而不是在主应用程序中?

我的库的相关代码:

@Service
public class MyService {
    @PreAuthorize("hasAuthority('ADMIN')")
    public void delete (long id){
       .....
    }
}
@RunWith(SpringRunner.class)
public class MyServiceTest {

    private MyService service;


    @Test
    @WithAnonymousUser
    public void deleteShouldFailIfAnonymous() {
         ... Verify exception thrown
    }


    @Test
    @WithMockUser(authorities = 'USER')
    public void deleteShouldFailIfNotAdmin() {
         ... Verify exception thrown
    }

    @Test
    @WithMockUser(authorities = 'ADMIN')
    public void deleteShouldPass() {
         ... Should pass
    }
}

我正在尝试添加@EnableGlobalMethodSecurity(prePostEnabled = true)但没有运气。如前所述,SecurityConfiguration 加载在主应用程序中,它不存在于库模块中。

我可以@PreAuthorize在模块中测试还是应该将其移动到主应用程序?如果可能的话,我想把它放在模块中。或者也许我可以创建一个仅用于测试的上下文,但不知道该怎么做。

4

2 回答 2

0

您可以使用 MockMvc 进行测试。这将有助于在集成测试时进行模块测试。


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class SecurityTests {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    @Before
    public void setup() {
        mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
    }

    @WithMockUser(roles="ADMIN")
    @Test
    public void withMockUser() {
        mvc.perform(get("......"))

    }
}
于 2020-06-05T14:51:39.533 回答
0

像方面这样的面向方面的特性@PreAuthorize被实现为advice。通常,这意味着 Spring 将创建一个装饰器接口来拦截方法调用,执行通知(在这种情况下,检查条件并在失败时抛出异常),然后将调用发送到服务对象。

当您使用 时new MyService,您将创建一个没有实现建议的包装器的裸对象,因此您不会看到应用了安全性、验证、缓存等。要查看您想要的行为,您需要@Autowired使用 Spring 测试支持来制作您的测试 bean。

于 2020-06-05T18:25:31.023 回答