使用自定义 bean 测试 PreAuthorize 注释
Posted
技术标签:
【中文标题】使用自定义 bean 测试 PreAuthorize 注释【英文标题】:Testing PreAuthorize annotations with custom beans 【发布时间】:2020-10-08 09:06:39 【问题描述】:我正在尝试在 Spring Boot 中的服务方法上测试我的 PreAuthorize
注释。我已经设法让它评估 SPeL 表达式,但是在引用自定义 bean 时它会失败。
我正在测试的服务方法:
@PreAuthorize("hasPermission(#eventId.id(), @eventTypePermission.target, @eventTypePermission.write())")
public EventTypeId retrieveEventTypeIdForEventId(EventId eventId)
return null;
测试代码:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class TestConfig extends GlobalMethodSecurityConfiguration
@Override
protected MethodSecurityExpressionHandler createExpressionHandler()
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new PermissionEvaluatorProxyTest());
return expressionHandler;
@Bean
public EventTypePermission permission()
return new EventTypePermission();
@Component
@Slf4j
class PermissionEvaluatorProxyTest implements PermissionEvaluator
@Autowired
public PermissionEvaluatorProxyTest()
@Override
public boolean hasPermission(
Authentication authentication, Object targetType, Object permission)
return true;
@Override
public boolean hasPermission(
Authentication authentication, Serializable targetId, String targetType, Object permission)
return true;
@Import(TestConfig.class)
@RunWith(SpringRunner.class)
@SpringBootTest(classes=EventUpdater.class)
public class EventUpdaterTest
@Autowired
private EventUpdater eventUpdater;
@MockBean
private EventRepository repository;
@MockBean
private EventTypePermission eventTypePermission;
@Before
public void setup()
@Test
@WithMockUser(username="test")
public void test()
eventUpdater.retrieveEventTypeIdForEventId(new EventId(UUID.randomUUID()));
错误是:
java.lang.IllegalArgumentException: Failed to evaluate expression 'hasPermission(#eventId.id(), @eventTypePermission.target, @eventTypePermission.write())'
...
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean 'eventTypePermission'
深入研究它失败了,因为 SPeL 表达式使用的 bean 解析器实例为空。关于为什么会出现这种情况以及如何设置 bean 解析器以便它能够返回 EventTypePermission
的实例的任何想法?
我还尝试将@SpringBootTest(classes=EventUpdater.class)
更改为@SpringBootTest(classes=EventUpdater.class, EventTypePermission.class)
,但没有成功。
【问题讨论】:
【参考方案1】:通过在配置类上显式设置应用程序上下文使其工作:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class TestConfig extends GlobalMethodSecurityConfiguration
private ApplicationContext applicationContext;
@Autowired
public TestConfig(ApplicationContext applicationContext)
this.applicationContext = applicationContext;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler()
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new PermissionEvaluatorProxyTest());
expressionHandler.setApplicationContext(applicationContext);
return expressionHandler;
还必须更新SpringTestClass
注释以包含EventTypePermission
:
@SpringBootTest(classes=EventUpdater.class, EventTypePermission.class)
,而不是在 TestConfig
类中定义 Bean。
【讨论】:
以上是关于使用自定义 bean 测试 PreAuthorize 注释的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Security Bean 中模拟自定义 UserService 详细信息以进行单元测试?