英文:
How do I unit test spring security @PreAuthorize custom expression
问题
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("@messageSecurityService.isAuthorized(#userAuthentication)")
public void sendMessage(@AuthenticationPrincipal UserAuthentication userAuthentication,
@RequestBody SendMessageRequest sendMessageRequest) {
// ......
}
java.lang.IllegalArgumentException: Failed to evaluate expression '@messageSecurityService.isAuthorized(#userAuthentication)'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30)
at org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice.before(ExpressionBasedPreInvocationAdvice.java:59)
// ... (more stack trace)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1058E: A problem occurred when trying to resolve bean 'messageSecurityService':'Could not resolve bean reference against BeanFactory'
at org.springframework.expression.spel.ast.BeanReference.getValueInternal(BeanReference.java:59)
// ... (more stack trace)
Caused by: org.springframework.expression.AccessException: Could not resolve bean reference against BeanFactory
at org.springframework.context.expression.BeanFactoryResolver.resolve(BeanFactoryResolver.java:54)
// ... (more stack trace)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'messageSecurityService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:775)
// ... (more stack trace)
To make the expression resolve the bean:
- Ensure that you have a Spring bean named 'messageSecurityService' registered in your application context.
- Make sure that the bean is properly configured and initialized.
- Confirm that the bean's name matches exactly with the one used in the
@PreAuthorize
expression (@messageSecurityService
). - If you are writing a unit test, you can use the
@MockBean
annotation to mock theMessageSecurityService
bean. Make sure to properly configure the mock's behavior in your test.
Example usage of @MockBean
in a test class:
@RunWith(SpringRunner.class)
@WebMvcTest(YourController.class)
public class YourControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private MessageSecurityService messageSecurityService;
// ... your test methods
}
Make sure to configure the behavior of the messageSecurityService
mock in your test methods according to your test scenarios.
英文:
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("@messageSecurityService.isAuthorized(#userAuthentication)")
public void sendMessage(@AuthenticationPrincipal UserAuthentication userAuthentication,
@RequestBody SendMessageRequest sendMessageRequest) {
......
}
I want to write the test of this endpoint, but I am getting the following error.
java.lang.IllegalArgumentException: Failed to evaluate expression '@messageSecurityService.isAuthorized(#userAuthentication)'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30)
at org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice.before(ExpressionBasedPreInvocationAdvice.java:59)
at org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter.vote(PreInvocationAuthorizationAdviceVoter.java:72)
at org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter.vote(PreInvocationAuthorizationAdviceVoter.java:40)
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:63)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1058E: A problem occurred when trying to resolve bean 'messageSecurityService':'Could not resolve bean reference against BeanFactory'
at org.springframework.expression.spel.ast.BeanReference.getValueInternal(BeanReference.java:59)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:53)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:89)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:300)
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:26)
... 94 common frames omitted
Caused by: org.springframework.expression.AccessException: Could not resolve bean reference against BeanFactory
at org.springframework.context.expression.BeanFactoryResolver.resolve(BeanFactoryResolver.java:54)
at org.springframework.expression.spel.ast.BeanReference.getValueInternal(BeanReference.java:55)
... 99 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'messageSecurityService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:775)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1221)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:273)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105)
at org.springframework.context.expression.BeanFactoryResolver.resolve(BeanFactoryResolver.java:51)
... 100 common frames omitted
How can I make the expression resolve bean ?
Using
@MockBean
MessageSecurityService didn't work.
答案1
得分: 2
你是否已经对 @MockBean 的返回进行了桩设,例如:
@MockBean(name = "messageSecurityService")
public MessageSecurityService messageSecurityService;
@Test
public void testing(){
when(messageSecurityService.isAuthorized(anyString())).thenReturn("somethingHere");
//rest of your assertions
}
同时,你是否在测试类中添加了以下内容:
@BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
}
英文:
Have you stub the return of the @MockBean e.g
@MockBean(name = "messageSecurityService")
public MessageSecurityService messageSecurityService;
@Test
public void testing(){
when(messageSecurityService.isAuthorized(anyString())).thenReturn("somethingHere");
//rest of your assertions
}
also have you added the following in your test class:
@BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论