前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >还在回放Hoverfly录制的死数据吗?

还在回放Hoverfly录制的死数据吗?

作者头像
Antony
发布2021-04-13 14:29:20
5120
发布2021-04-13 14:29:20
举报
文章被收录于专栏:软件测试那些事

在原先的文章 真香系列之2-自动录制回放的Hoverfly-java-Junit5 中,笔者提到了关于录制文件中数据修改的问题。

在实际的项目中,当服务间进行内部服务调用时,出于鉴权的需要,会在请求体中带上timeStamp,token等信息。这些信息经过录制之后会存放在指定的JSON文件之中。为了能够在用例执行时,可以让用例能够正确执行,需要手工将JSON文件中的匹配模式修改为glob,并将中的timeStamp,token的具体值修改为通配符*。如以下的案例,

代码语言:javascript
复制
"body": [    {       
"matcher": "glob",        
"value": "timeStamp=*,token=*"    }
]

在目前的方案中,通过在录制并完成写文件之后重新进行调整的方式实现了修改。也就是

1)继承HoverflyExtension并复写afterAll方法,

2)首先根据现有方法来生成JSON文件,

3)然后根据capturePath来获取已生成的文件,并编写modify方法来修改并保存这个文件。

实际上,Hoverfly提供了SimulationPreprocessor 这一机制来让用户动态修改模拟数据。

The SimulationPreprocessor interface lets you apply custom transformation to the Simulation object before importing to Hoverfly. This can be useful if you want to batch add/remove matchers, or update matcher types, like weakening matching criteria of captured data. https://hoverfly-java.readthedocs.io/en/latest/pages/corefunctionality/configuration.html#simulation-preprocessor

而在Hoverfly-java中,也为此提供了一个SimulationPreprocessor类,这个功能接口类只含有一个方法accept(Simulation simulation) 。

代码语言:javascript
复制
ackage io.specto.hoverfly.junit.core;
import io.specto.hoverfly.junit.core.model.Simulation;
import java.util.function.Consumer;
/**
 * A SimulationPreprocessor processes{@link Simulation} instances prior to
 * handing them over to Hoverfly client. As {@link Simulation} instances are
 * mutable, you may directly modify the simulation be adding additional
 * request-response-pairs or weakening for example request matching of
 * previously captured session.
 */
@FunctionalInterface
public interface SimulationPreprocessor extends Consumer<Simulation> {
    /**
     * {@inheritDoc}
     * <p>
     * Allows to modify the given mutable {@link Simulation} instance,
     * by, for example, adapting request matching.
     * </p>
     */
    @Override
    void accept(Simulation simulation);
}

与之前的案例类似,选取Hoverfly官网提供的测试案例, 在模拟文件中有如下的请求需要修改为通配。

代码语言:javascript
复制
"body": [
   {
      "matcher": "exact",
      "value": "{\"flightId\": \"1\"}"
   }
]

可以通过定义一个类来实现这个接口,然后完成对数据的运行时修改。

代码语言:javascript
复制
package io.specto.hoverfly.junit5;
import io.specto.hoverfly.junit.core.Hoverfly;
import io.specto.hoverfly.junit.core.SimulationPreprocessor;
import io.specto.hoverfly.junit.core.model.RequestFieldMatcher;
import io.specto.hoverfly.junit.core.model.RequestResponsePair;
import io.specto.hoverfly.junit.core.model.Simulation;
import io.specto.hoverfly.junit5.api.HoverflyConfig;
import io.specto.hoverfly.junit5.api.HoverflySimulate;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
@HoverflySimulate(
        config = @HoverflyConfig(
                simulationPreprocessor = PreProcessTest.CustomSimulationPreprocessor.class
        ),        source = @HoverflySimulate.Source(value = "hoverfly/test-service.json",
        type = HoverflySimulate.SourceType.CLASSPATH)
)
@ExtendWith(HoverflyExtension.class)
public class PreProcessTest {
    static class CustomSimulationPreprocessor implements SimulationPreprocessor {
        @Override
        public void accept(Simulation simulation) {
          //遍历请求响应数据,找出请求中的请求体中的body,如果body中包含了flightId,
            // 则将matcher修改为glob, flightId的值修改为*。
            Set<RequestResponsePair> pairs= simulation.getHoverflyData().getPairs();
            pairs.forEach(requestResponsePair -> requestResponsePair.getRequest().getBody()
                    .stream().forEach(body->{
                       if( ((String) body.getValue()).contains("flightId")){
                           body.setMatcher(RequestFieldMatcher.MatcherType.GLOB);
                           body.setValue("*");
                       }}));
        }
    }

}

然后在这个类中写一个单元测试用例来测试一下。

代码语言:javascript
复制
    @Test
    void shouldUseCustomPorts(Hoverfly hoverfly) {

Set<RequestResponsePair> pairs= hoverfly.getSimulation().getHoverflyData().getPairs();
pairs.forEach(requestResponsePair -> requestResponsePair.getRequest().getBody()
                .stream().forEach(body->{
                   if( ((String) body.getValue()).contains("flightId")){
assertThat(body.getMatcher()).isEqualTo(RequestFieldMatcher.MatcherType.GLOB);
                            }
                        }));
    }

可以看到,虽然在模拟文件中的matcher为exact,但是经过在CustomSimulationPreprocessor类中的修改之后,从测试用例中获取到的hoverfly实例中所包含的该数据已经被修改成了glob。也就是动态修改成功了。

当然,相比于在录制时就地修改的一劳永逸,用这种方式来修改请求其实也比较繁琐,需要在各个引用此模拟文件的类中使用CustomSimulationPreprocessor。笔者看来,这个方式更合适的应用场景应该是扮演Hoverfly Middleware的作用,也就是通过这个接口来动态修改响应结果,类似DataBaseRider中的动态数据替换,如NOW占位符则自动返回系统当前时间。感兴趣的读者可以参考示例自行实现。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试那些事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档