如何让aspectj在webtestclient中工作?
How to let aspectj worked in webtestclient?
我有一些 apis 由 spring webflux 实现。现在我需要写一些 UT 来测试它。我用spock写UT代码,用WebTestClient.bindToRouterFunction方法创建一个mock server。它也有效。但是我发现我有一个 ParaCheckAspect 来检查 api 的参数,它不起作用,因为我还没有创建 Spring IOC。我必须查看 WebTestClient apis,它没有任何 api 来注册我的 ParaCheckAspect。如果您知道解决问题的方法,请告诉我。
我看过 spring 文档 https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#webtestclient。它没有这方面的有效信息。
/**
* check Parameters is validate
*/
@Aspect
@Slf4j
@Component
public class ParaCheckAspect {
@Around("execution (* com.winston.springboot.handler..*(..))")
public Object validate(ProceedingJoinPoint point) throws Throwable {
for (int i = 0; i < point.getArgs().length; i++) {
if (point.getArgs()[i] instanceof Mono) {
point.getArgs()[i] = ((Mono<?>) point.getArgs()[i])
.doOnNext(this::check)
.onErrorResume(e -> Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST,e.getMessage())));
} else if (point.getArgs()[i] instanceof Flux) {
point.getArgs()[i] = ((Flux<?>) point.getArgs()[i])
.doOnNext(this::check)
.onErrorResume(e -> Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST,e.getMessage())));
}
}
return point.proceed(point.getArgs());
}
private void check(Object obj) {
//some validator code
}
}
import com.winston.springboot.config.routers.UserRouter
import com.winston.springboot.entity.User
import com.winston.springboot.handler.UserHandler
import org.mockito.InjectMocks
import org.mockito.MockitoAnnotations
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.web.reactive.function.BodyInserters
import spock.lang.Shared
import spock.lang.Specification
class UserHandlerSpec extends Specification {
@Shared
WebTestClient testClient
@InjectMocks
UserHandler userHandler
void setup() {
MockitoAnnotations.initMocks(this)
def function = routeFunction()
def routeFunctionSpec = WebTestClient.bindToRouterFunction(function)
testClient = routeFunctionSpec
.configureClient()
.baseUrl("http://127.0.0.1:8089")
.build()
}
def 'test userSave'() {
given:
User user = User.builder().name("lina").age(10).build()
when:
testClient.post().uri("/user")
.body(BodyInserters.fromObject(user))
.exchange()
.expectStatus()
.isOk()
.expectBody(User.class)
.returnResult();
then:
noExceptionThrown();
}
def routeFunction() {
return new UserRouter().userRouterFunction(userHandler);
}
}
这还不是答案,目前只是与 OP 通信的一种方式,因为我需要 space 到 post 代码和调用堆栈,这是不可能在评论中。
免责声明:我从未使用过Gradle(仅 Maven)并且对 Webflux 了解为零。但有几点我可以说:
- 克隆您的项目时,我注意到的第一件事是您在 build.gradle 中忘记了
apply plugin: "groovy"
。没有它,你的 Spock 测试甚至不会被编译并且 运行.
- 添加 Groovy 插件后,运行测试产生以下执行:
Method org.springframework.test.web.reactive.server.WebTestClient.bindToRouterFunction(Lorg/springframework/web/reactive/function/server/RouterFunction;)Lorg/springframework/test/web/reactive/server/
java.lang.IncompatibleClassChangeError: Method org.springframework.test.web.reactive.server.WebTestClient.bindToRouterFunction(Lorg/springframework/web/reactive/function/server/RouterFunction;)Lorg/springframework/test/web/reactive/server/
at com.winston.webflux.UserHandlerSpec.setup(UserHandlerSpec.groovy:25)
com.winston.webflux.UserHandlerSpec > test userSave FAILED
java.lang.IncompatibleClassChangeError at UserHandlerSpec.groovy:25
这是你的问题吗?您从未说过您实际遇到的问题,只是 "AspectJ"(您真正的意思是 Spring AOP)在您的测试中不起作用。
还有一个示例应用程序。我可以启动它,但是我需要做什么才能启动这个方面?抱歉,我真的不是 Spring 人,我只是 AOP 专家,也了解 Spock。所以请先帮我理解问题。如果我在浏览器中打开 http://localhost:8080/user/,我只会得到一个 "Whitelabel Error Page",控制台上没有任何日志输出。
如果您正在使用 spring,您应该包括 spock-spring
模块,这会为您的 Specification
添加 spring 支持。然后你需要使用 @SpringBootTest
或类似的 spring 注释,例如@WebFluxTest
,并注入您的处理程序。这样 spring 创建实例并应用 AOP 拦截器。
我有一些 apis 由 spring webflux 实现。现在我需要写一些 UT 来测试它。我用spock写UT代码,用WebTestClient.bindToRouterFunction方法创建一个mock server。它也有效。但是我发现我有一个 ParaCheckAspect 来检查 api 的参数,它不起作用,因为我还没有创建 Spring IOC。我必须查看 WebTestClient apis,它没有任何 api 来注册我的 ParaCheckAspect。如果您知道解决问题的方法,请告诉我。
我看过 spring 文档 https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#webtestclient。它没有这方面的有效信息。
/**
* check Parameters is validate
*/
@Aspect
@Slf4j
@Component
public class ParaCheckAspect {
@Around("execution (* com.winston.springboot.handler..*(..))")
public Object validate(ProceedingJoinPoint point) throws Throwable {
for (int i = 0; i < point.getArgs().length; i++) {
if (point.getArgs()[i] instanceof Mono) {
point.getArgs()[i] = ((Mono<?>) point.getArgs()[i])
.doOnNext(this::check)
.onErrorResume(e -> Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST,e.getMessage())));
} else if (point.getArgs()[i] instanceof Flux) {
point.getArgs()[i] = ((Flux<?>) point.getArgs()[i])
.doOnNext(this::check)
.onErrorResume(e -> Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST,e.getMessage())));
}
}
return point.proceed(point.getArgs());
}
private void check(Object obj) {
//some validator code
}
}
import com.winston.springboot.config.routers.UserRouter
import com.winston.springboot.entity.User
import com.winston.springboot.handler.UserHandler
import org.mockito.InjectMocks
import org.mockito.MockitoAnnotations
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.web.reactive.function.BodyInserters
import spock.lang.Shared
import spock.lang.Specification
class UserHandlerSpec extends Specification {
@Shared
WebTestClient testClient
@InjectMocks
UserHandler userHandler
void setup() {
MockitoAnnotations.initMocks(this)
def function = routeFunction()
def routeFunctionSpec = WebTestClient.bindToRouterFunction(function)
testClient = routeFunctionSpec
.configureClient()
.baseUrl("http://127.0.0.1:8089")
.build()
}
def 'test userSave'() {
given:
User user = User.builder().name("lina").age(10).build()
when:
testClient.post().uri("/user")
.body(BodyInserters.fromObject(user))
.exchange()
.expectStatus()
.isOk()
.expectBody(User.class)
.returnResult();
then:
noExceptionThrown();
}
def routeFunction() {
return new UserRouter().userRouterFunction(userHandler);
}
}
这还不是答案,目前只是与 OP 通信的一种方式,因为我需要 space 到 post 代码和调用堆栈,这是不可能在评论中。
免责声明:我从未使用过Gradle(仅 Maven)并且对 Webflux 了解为零。但有几点我可以说:
- 克隆您的项目时,我注意到的第一件事是您在 build.gradle 中忘记了
apply plugin: "groovy"
。没有它,你的 Spock 测试甚至不会被编译并且 运行. - 添加 Groovy 插件后,运行测试产生以下执行:
Method org.springframework.test.web.reactive.server.WebTestClient.bindToRouterFunction(Lorg/springframework/web/reactive/function/server/RouterFunction;)Lorg/springframework/test/web/reactive/server/
java.lang.IncompatibleClassChangeError: Method org.springframework.test.web.reactive.server.WebTestClient.bindToRouterFunction(Lorg/springframework/web/reactive/function/server/RouterFunction;)Lorg/springframework/test/web/reactive/server/
at com.winston.webflux.UserHandlerSpec.setup(UserHandlerSpec.groovy:25)
com.winston.webflux.UserHandlerSpec > test userSave FAILED
java.lang.IncompatibleClassChangeError at UserHandlerSpec.groovy:25
这是你的问题吗?您从未说过您实际遇到的问题,只是 "AspectJ"(您真正的意思是 Spring AOP)在您的测试中不起作用。
还有一个示例应用程序。我可以启动它,但是我需要做什么才能启动这个方面?抱歉,我真的不是 Spring 人,我只是 AOP 专家,也了解 Spock。所以请先帮我理解问题。如果我在浏览器中打开 http://localhost:8080/user/,我只会得到一个 "Whitelabel Error Page",控制台上没有任何日志输出。
如果您正在使用 spring,您应该包括 spock-spring
模块,这会为您的 Specification
添加 spring 支持。然后你需要使用 @SpringBootTest
或类似的 spring 注释,例如@WebFluxTest
,并注入您的处理程序。这样 spring 创建实例并应用 AOP 拦截器。