在 Java Spring Boot 中发出模拟 SpEL 表达式函数

Issue mocking SpEL expression functions in Java Spring Boot

在名为 ProductController 的 RestController 中,我定义了一些 PreAuthorize 函数,例如:

@PreAuthorize("@userIsOwnerOfEntity.apply(#id, principal.claims['user_id'])")

此函数会先检查 userId 是否是产品的实际所有者,然后才能 save/update 实体。这是另一个名为 ProductControllerSecurity.class 的文件中的实现,该文件被注释为服务。

@Autowired
public GetProductImpl getProductImpl;

@Bean
public BiFunction<ProductDto, String, Boolean> userIsOwnerOfEntity() {
    return (product, userId) -> {
       Product check = getProductImpl.execute(product.getProductId());
       return check.getUserId().toString().equals(userId);
    };
}

现在我想在 ProductControllerTest.class 中模拟 userIsOwnerOfEntity 功能,但我碰壁了。

在我的测试中,我有以下模拟实现:

@Autowired public BiFunction<ProductDto, String, Boolean> userIsOwnerOfEntity;
when(userIsOwnerOfEntity.apply(any(ProductDto.class), any(String.class))).thenReturn(true);

测试导入一个名为 ProductControllerSecurityTest.class 的文件,其中包含以下 Bean:

@MockBean(name="userIsOwnerOfEntity") public BiFunction<ProductDto, String, Boolean> userIsOwnerOfEntity;

所以我假设模拟的 SpEL 函数应该 return true。但是我收到以下错误;

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "org.springframework.expression.Expression.getValue(org.springframework.expression.EvaluationContext, java.lang.Class)" is null

我相信这告诉我 SpEL 函数不是 returning true

有什么指点吗?

因此,我需要将@SpringBootTest 与@AutoConfigureMockMvc 一起使用,而不是使用@WebMvcTest。然后它正确地模拟了 SpEL 表达式。

when(userIsOwnerOfEntity.apply(any(ProductDto.class), anyString())).thenReturn(true);

上面的代码现在按预期运行。

这解决了以下错误:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1058E: A problem occurred when trying to resolve bean 'Could not resolve bean reference against BeanFactory'

Caused by: org.springframework.expression.AccessException: Could not resolve bean reference against BeanFactory

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userIsOwnerOfEntity' available