使用Spock进行单元测试Spring Cloud Gateway过滤器

我正在使用响应式全局过滤器在网关响应中添加cookie,例如:

chain.filter(exchange).then(<a mono relevant to response>)

当我尝试使用spock进行测试时,不会从已存根的Mono中调用 then 方法。

过滤器本身:

@Override
public Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain) {
    return chain.filter(exchange)
            .then(refreshCookiesMono(exchange));
}

private Mono<Void> refreshCookiesMono(ServerWebExchange exchange) {
    return Mono.fromRunnable(() -> {
        //interactions with *exchange* and *chain*
    });
}

尽管最后以0 * _结束,该测试仍通过:

@Subject
CookieFilter cookieFilter = new CookieFilter(cookieHelper)
...
ServerWebExchange exchange = Mock ServerWebExchange
GatewayFilterChain chain = Mock GatewayFilterChain
Mono<Void> mono = Mock Mono

...

def "cookieFilter refreshes the cookie with a new value"() {
    given:

    when:
    cookieFilter.filter(exchange,chain)

    then:
    1 * chain.filter(exchange) >> mono
    0 * _
}

但是在代码中,我从 .filter 方法返回的mono中调用 .then

为什么不考虑 mono.then()?当然,当我尝试测试所有基本逻辑时,spock找不到交互。

simonfeng88 回答:使用Spock进行单元测试Spring Cloud Gateway过滤器

chain.filter(exchange)返回您模拟的单声道实例。

您尚未对该模拟物指定任何期望值(我相信这是您问题的答案),因此测试并没有真正检查过滤器,仅检查了该过滤器是打给chain.filter(exchange)的电话。

除了Mocks之外,Spock还支持Stub,并且与许多其他框架不同,它们之间存在差异:

模拟是“较重的”,您可以对它们进行验证(在“ then”块中),存根更为“轻巧”,通常可以在“给定”块中指定对它们的期望。 通常,如果要模拟某种交互并将测试基于围绕该交互进行管理的协议,则可以使用Mocks,在其他情况下,则首选Stub。

,

失去希望端到端地测试过滤器的方法,我已经在一个单独的包私有方法中提取了可运行对象,并在没有Monos和任何其他反应性元素的情况下对其进行了测试。

过滤器中的代码现在如下所示:

@Override
public Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain) {
    return chain.filter(exchange)
            .then(Mono.fromRunnable(refreshCookies(exchange)));
}

Runnable refreshCookies(ServerWebExchange exchange) {
    return () -> {
        //magic happens here ....
    };
}

任何其他线索和重构建议都将受到赞赏。

本文链接:https://www.f2er.com/3129653.html

大家都在问