繁体   English   中英

使用 spock 对 spring 云网关过滤器进行单元测试

[英]Unit testing spring cloud gateway filters with spock

我使用反应式全局过滤器在网关响应中添加 cookies 为:

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

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

过滤器本身:

@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 找不到交互。

chain.filter(exchange)返回您模拟的 mono 的实例。

您没有对该模拟指定任何期望(我相信这是您问题的答案),因此测试并没有真正检查过滤器,它只检查是否有一次调用chain.filter(exchange) .

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

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

失去了端到端测试过滤器的希望,我在一个单独的 package 私有方法中提取了我的可运行文件,并在没有 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 ....
    };
}

感谢任何进一步的线索和重构建议。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM