I have some apis implements by spring webflux. Now i need to write some UT to test it. I write the UT code by spock, and create a mock server by the method WebTestClient.bindToRouterFunction. It worked as well. But i found that i have an ParaCheckAspect to check the api's parameters, it doesn't work because I have not created Spring IOC . I have to look the WebTestClient apis, it not has any api to register my ParaCheckAspect. Please tell me if you know any way to resolve it.
I have look the spring document https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#webtestclient. It not has effective info for this.
/**
* 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);
}
}
If you are using spring, you should include the spock-spring
module, this adds spring support to your Specification
. Then you need to use @SpringBootTest
or a similar spring annotation, e.g. @WebFluxTest
, and inject your handlers. This ways spring creates the instances and applies the AOP interceptors.