[英]Test service that uses eureka and ribbon
我正在使用帶有netflix堆棧和spring boot的微服務構建一個應用程序。 讓我感到困惑的一件事是我還沒有集成測試,我可以在這里模擬周圍的服務。
所以,我有一個服務A,它是一個帶有功能區的eureka客戶端,用於在通話期間將eureka名稱解析為注冊服務B的URL。
理想情況下,我想用springtest注釋啟動應用程序,使用wiremock來模擬服務B,然后調用服務A的方法,這應該使用服務的符號名稱來調用我的模擬服務B.
有人已經解決了嗎? 我已經搜索了人們這樣做的博客條目等,但找不到任何...
我知道SO文章Mock是Eureka Feign客戶端進行單元測試,但據我所知,這只會阻止發現客戶端抱怨。
以下代碼(摘自https://github.com/Netflix/eureka/blob/a7a8d278e6399bbff5faa49b9fcbcd7ea9e854f4/eureka-core/src/test/java/com/netflix/eureka/mock/MockRemoteEurekaServer.java )可能對您有所幫助;
public class MockRemoteEurekaServer extends ExternalResource {
public static final String EUREKA_API_BASE_PATH = "/eureka/v2/";
private final Map<String, Application> applicationMap;
private final Map<String, Application> applicationDeltaMap;
private final Server server;
private boolean sentDelta;
private int port;
private volatile boolean simulateNotReady;
public MockRemoteEurekaServer(int port, Map<String, Application> applicationMap,
Map<String, Application> applicationDeltaMap) {
this.applicationMap = applicationMap;
this.applicationDeltaMap = applicationDeltaMap;
ServletHandler handler = new AppsResourceHandler();
EurekaServerConfig serverConfig = new DefaultEurekaServerConfig();
EurekaServerContext serverContext = mock(EurekaServerContext.class);
when(serverContext.getServerConfig()).thenReturn(serverConfig);
handler.addFilterWithMapping(ServerRequestAuthFilter.class, "/*", 1).setFilter(new ServerRequestAuthFilter(serverContext));
handler.addFilterWithMapping(RateLimitingFilter.class, "/*", 1).setFilter(new RateLimitingFilter(serverContext));
server = new Server(port);
server.addHandler(handler);
System.out.println(String.format(
"Created eureka server mock with applications map %s and applications delta map %s",
stringifyAppMap(applicationMap), stringifyAppMap(applicationDeltaMap)));
}
@Override
protected void before() throws Throwable {
start();
}
@Override
protected void after() {
try {
stop();
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
public void start() throws Exception {
server.start();
port = server.getConnectors()[0].getLocalPort();
}
public void stop() throws Exception {
server.stop();
}
public boolean isSentDelta() {
return sentDelta;
}
public int getPort() {
return port;
}
public void simulateNotReady(boolean simulateNotReady) {
this.simulateNotReady = simulateNotReady;
}
private static String stringifyAppMap(Map<String, Application> applicationMap) {
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, Application> entry : applicationMap.entrySet()) {
String entryAsString = String.format("{ name : %s , instance count: %d }", entry.getKey(),
entry.getValue().getInstances().size());
builder.append(entryAsString);
}
return builder.toString();
}
private class AppsResourceHandler extends ServletHandler {
@Override
public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)
throws IOException, ServletException {
if (simulateNotReady) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
String authName = request.getHeader(AbstractEurekaIdentity.AUTH_NAME_HEADER_KEY);
String authVersion = request.getHeader(AbstractEurekaIdentity.AUTH_VERSION_HEADER_KEY);
String authId = request.getHeader(AbstractEurekaIdentity.AUTH_ID_HEADER_KEY);
Assert.assertNotNull(authName);
Assert.assertNotNull(authVersion);
Assert.assertNotNull(authId);
Assert.assertTrue(!authName.equals(ServerRequestAuthFilter.UNKNOWN));
Assert.assertTrue(!authVersion.equals(ServerRequestAuthFilter.UNKNOWN));
Assert.assertTrue(!authId.equals(ServerRequestAuthFilter.UNKNOWN));
for (FilterHolder filterHolder : this.getFilters()) {
filterHolder.getFilter().doFilter(request, response, new FilterChain() {
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
// do nothing;
}
});
}
String pathInfo = request.getPathInfo();
System.out.println(
"Eureka resource mock, received request on path: " + pathInfo + ". HTTP method: |" + request
.getMethod() + '|');
boolean handled = false;
if (null != pathInfo && pathInfo.startsWith("")) {
pathInfo = pathInfo.substring(EUREKA_API_BASE_PATH.length());
if (pathInfo.startsWith("apps/delta")) {
Applications apps = new Applications();
for (Application application : applicationDeltaMap.values()) {
apps.addApplication(application);
}
apps.setAppsHashCode(apps.getReconcileHashCode());
sendOkResponseWithContent((Request) request, response, toJson(apps));
handled = true;
sentDelta = true;
} else if (pathInfo.startsWith("apps")) {
Applications apps = new Applications();
for (Application application : applicationMap.values()) {
apps.addApplication(application);
}
apps.setAppsHashCode(apps.getReconcileHashCode());
sendOkResponseWithContent((Request) request, response, toJson(apps));
handled = true;
}
}
if (!handled) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
"Request path: " + pathInfo + " not supported by eureka resource mock.");
}
}
private void sendOkResponseWithContent(Request request, HttpServletResponse response, String content)
throws IOException {
response.setContentType("application/json; charset=UTF-8");
response.setStatus(HttpServletResponse.SC_OK);
response.getOutputStream().write(content.getBytes("UTF-8"));
response.getOutputStream().flush();
request.setHandled(true);
System.out.println("Eureka resource mock, sent response for request path: " + request.getPathInfo() +
" with content" + content);
}
}
private String toJson(Applications apps) throws IOException {
return new EurekaJsonJacksonCodec().getObjectMapper(Applications.class).writeValueAsString(apps);
}
}
一種選擇是使用Camel來模擬/替換Eureka端點。 應該有一個配置告訴你的應用程序在哪里尋找Eureka,所以在你的測試配置中覆蓋它以指向新的端點。
然后使用jetty或http在test / src中創建一個Camel路由來表示這個新端點,它將返回LoadBalancerClient期望的響應。 該響應將具有正在測試的URI(即您的應用程序)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.