Spring 在库模块中启动测试 @PreAuthorize
Spring Boot Test @PreAuthorize in a Library Module
我有一个使用 Spring Boot 1.5.21 编写的库模块。
该库有一个 @Service
,其中一些方法用 @PreAutorize
注释,只允许具有 ADMIN 权限的用户执行某些操作,例如 删除.
然后我有一个使用该库的 Spring 启动应用程序。如果我 运行 应用程序并手动测试它,它就可以工作。只有管理员可以删除。我想为它写测试。
我正在考虑为模块和主应用程序编写单独的测试。在我的模块中,我可以成功地对操作进行单元测试。但是我在测试 @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
还是应该将其移至主应用程序?如果可能的话,我想把它放在模块中。或者,也许我可以创建一个仅用于测试的上下文,但不知道该怎么做。
您可以使用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("......"))
}
}
@PreAuthorize
等面向方面的功能实现为 建议 。通常,这意味着 Spring 将创建一个 decorator interface 拦截方法调用,执行建议(在这种情况下,检查条件并在失败时抛出异常),然后发送调用到服务对象。
当您使用 new MyService
时,您正在创建一个没有实现建议的包装器的裸对象,因此您不会看到应用的安全性、验证、缓存等。要查看您想要的行为,您需要使用 Spring 测试支持来制作测试 bean @Autowired
。
我有一个使用 Spring Boot 1.5.21 编写的库模块。
该库有一个 @Service
,其中一些方法用 @PreAutorize
注释,只允许具有 ADMIN 权限的用户执行某些操作,例如 删除.
然后我有一个使用该库的 Spring 启动应用程序。如果我 运行 应用程序并手动测试它,它就可以工作。只有管理员可以删除。我想为它写测试。
我正在考虑为模块和主应用程序编写单独的测试。在我的模块中,我可以成功地对操作进行单元测试。但是我在测试 @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
还是应该将其移至主应用程序?如果可能的话,我想把它放在模块中。或者,也许我可以创建一个仅用于测试的上下文,但不知道该怎么做。
您可以使用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("......"))
}
}
@PreAuthorize
等面向方面的功能实现为 建议 。通常,这意味着 Spring 将创建一个 decorator interface 拦截方法调用,执行建议(在这种情况下,检查条件并在失败时抛出异常),然后发送调用到服务对象。
当您使用 new MyService
时,您正在创建一个没有实现建议的包装器的裸对象,因此您不会看到应用的安全性、验证、缓存等。要查看您想要的行为,您需要使用 Spring 测试支持来制作测试 bean @Autowired
。