【问题标题】:Spring Boot Test @PreAuthorize in a Library Module库模块中的 Spring Boot 测试 @PreAuthorize
【发布时间】:2020-09-24 18:23:52
【问题描述】:

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

该库有一个@Service,其中一些方法用@PreAutorize 注释,只允许具有ADMIN 权限的用户执行某些操作,例如delete。 p>

然后我有一个使用该库的 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 还是应该将其移至主应用程序?如果可能的话,我想把它放在模块中。或者也许我可以创建一个仅用于测试的上下文,但不知道该怎么做。

【问题讨论】:

  • 您是如何在测试用例中获取服务实例的?
  • 我只是在测试的 setup() 方法中创建它的一个新实例,比如service = new MyService()

标签: java spring-boot spring-security spring-security-test


【解决方案1】:

@PreAuthorize 等面向方面的功能被实现为建议。通常,这意味着 Spring 将创建一个 decorator interface 来拦截方法调用,执行通知(在这种情况下,检查条件并在失败时抛出异常),然后将调用发送到服务对象。

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

【讨论】:

  • 谢谢!你完全正确!我现在设法测试我的图书馆。我创建了一个 TestApplication 并用 @SpringBootApplication 注释它,然后我自动连接了服务!
【解决方案2】:

您可以使用 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("......"))

    }
}

【讨论】:

  • @Controller 就是这种情况,我想测试@Service。并且不执行任何网络请求
猜你喜欢
  • 2020-01-30
  • 2018-01-01
  • 1970-01-01
  • 2015-03-23
  • 2016-04-16
  • 2018-04-15
  • 2021-10-14
  • 1970-01-01
  • 2021-08-01
相关资源
最近更新 更多