在之前的一文中 ,笔者介绍了如何通过SimulationPreprocessor这个接口来实现对Hoverfly录制的请求数据Request进行修改。
当时还立了一个flag,说这个套路也适合对响应数据Response进行修改。
例如,有这样的一个案例,
"response": {
"status": 200,
"body": "{\"bookingId\":\"1\",\"origin\":\"London\",\"destination\":\"Singapore\",\"time\":\"[NOW]\",\"_links\":{\"self\":{\"href\":\"http://localhost/api/bookings/1\"}}}",
在响应的body中,希望time这个字段可以返回动态时间,如当前系统时间,而不是一个固定录制的值。因此,将具体值用一个占位符[NOW]进行了替换。
然后写了一个类来实现这个替换。
static class TimeSimulationPreprocessor implements SimulationPreprocessor {
@Override
public void accept(Simulation simulation) {
HoverflyData originData= simulation.getHoverflyData();
Set<RequestResponsePair> pairs= new HashSet<>();
originData.getPairs().stream()
.forEach(p ->
{
Response origin= p.getResponse();
String body =origin.getBody();
String replaced= body.replace("[NOW]", LocalDateTime.now().toString());
Response rsp= new Response(origin.getStatus(),replaced,origin.isEncodedBody(),origin.isTemplated(),origin.getHeaders(),origin.getTransitionsState(),origin.getRemovesState(),origin.getFixedDelay(),origin.getLogNormalDelay()); RequestResponsePair pair =new RequestResponsePair(p.getRequest(),rsp);
pairs.add(pair);
});
//HoverflyData hoverflyData=new HoverflyData(pairs,simulation.getHoverflyData().getGlobalActions());
// simulation.setHoverflyData(hoverflyData);
simulation=new Simulation(new HoverflyData(pairs,simulation.getHoverflyData().getGlobalActions()), simulation.getHoverflyMetaData());
ObjectMapper mapper = new ObjectMapper();
try {
System.out.println("class::\n"+mapper.writeValueAsString(simulation));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
可以发现,这个过程相比之前的修改request,繁琐了很多。当时还为在意,然后写一个用例测试一下,
package io.specto.hoverfly.junit5;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.specto.hoverfly.junit.core.Hoverfly;
import io.specto.hoverfly.junit.core.SimulationPreprocessor;
import io.specto.hoverfly.junit.core.SslConfigurer;
import io.specto.hoverfly.junit.core.model.*;
import io.specto.hoverfly.junit5.api.HoverflyConfig;
import io.specto.hoverfly.junit5.api.HoverflySimulate;
import okhttp3.OkHttpClient;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
import static net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson;
@HoverflySimulate(
config = @HoverflyConfig(
simulationPreprocessor = PreProcessResponseTest.TimeSimulationPreprocessor.class
), source = @HoverflySimulate.Source(value = "hoverfly/test-service.json",
type = HoverflySimulate.SourceType.CLASSPATH)
)
@ExtendWith({HoverflyExtension.class})
public class PreProcessResponseTest {
private static OkHttpClient client;
@BeforeAll
static void init(Hoverfly hoverfly) {
SslConfigurer sslConfigurer = hoverfly.getSslConfigurer();
client = new OkHttpClient.Builder()
.sslSocketFactory(sslConfigurer.getSslContext().getSocketFactory(), sslConfigurer.getTrustManager())
.build();
}
@Test
void shouldUseCustomPorts(Hoverfly hoverfly) throws IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println("test::\n"+mapper.writeValueAsString(hoverfly.getSimulation()));
final okhttp3.Request request = new okhttp3.Request.Builder().url("https://www.my-test.com/api/bookings/1")
.build();
final okhttp3.Response response = client.newCall(request).execute();
System.out.println("test::\n"+mapper.writeValueAsString(response.body().string()));
assertThatJson(response.body().string()).node("bookingId").isStringEqualTo("1");
}
}
然后就被打脸了。。。
这个数据压根就没有被修改。虽然在预处理的类里面仿佛已经修改了。
看上去,Hoverfly在设计时就没打算让你修改Response。
1、Simluation类里面只有getHoverflyData方法,而没有set
simulation.setHoverflyData(hoverflyData);
这个方法是笔者自己改的源码。
2、接下来的HoverflyData、RequestResponsePair、Response一水全是只提供构造方法,然后成员变量全部final, 只提供getXXX,不提供setXXX方法。
public class Response {
private final Integer status;
private final String body;
private final boolean encodedBody;
private final boolean templated;
private final Map<String, List<String>> headers;
private final Map<String, String> transitionsState;
private final List<String> removesState;
private final Integer fixedDelay;
private final LogNormalDelay logNormalDelay;
@JsonCreator
public Response(
@JsonProperty("status") Integer status,
@JsonProperty("body") String body,
@JsonProperty("encodedBody") boolean encodedBody,
@JsonProperty("templated") boolean templated,
@JsonProperty("headers") Map<String, List<String>> headers,
@JsonProperty("transitionsState") Map<String, String> transitionsState,
@JsonProperty("removesState") List<String> removesState,
@JsonProperty("fixedDelay") Integer fixedDelay,
@JsonProperty("logNormalDelay") LogNormalDelay logNormalDelay)//...
}
看上去,要实现这样的需求,
1、要么自己fork一个Hoverfly-java,然后提供一个setHoverflyData方法,或者去修改Response等类。
2、说服Hoverfly-java团队修改设计?
3、用 middleware (python脚本 )注册到Hoverfly。。。用系统测试的套路来搞集成测试。
看来话不能说太满