14

Buduję aplikację za pomocą mikroserwisów ze stosem netflix i startem sprężynowym. Jedną z rzeczy, która mnie trapi jest to, że nie mam jeszcze testów integracyjnych, gdzie mogę wyśmiać otaczające usługi.Usługa testowa korzystająca z eureki i wstążki

Mam więc usługę A, która jest klientem eureka z wstążką, aby rozpoznać nazwę eureka na adres URL zarejestrowanej usługi B podczas połączenia.

Idealnie więc chcę uruchomić aplikację z adnotacjami integracji integracji z wiosennym bootowaniem, użyć wiremocka do symulacji usługi B, a następnie wywołać metodę usługi A, to powinno wywołać moją wyśmiewaną usługę B przy użyciu symbolicznej nazwy usługi .

Czy ktoś już to rozwiązał? Szukałem już wpisów blogów itp. Osób robiących to już, ale nie mogłem znaleźć żadnego ...

Wiem o artykule SO Mock an Eureka Feign Client for Unittesting, ale z tego, co widzę, to po prostu uniemożliwia klientowi odkrycia złożenie skargi.

+0

Ten post omawia kilka różnych podejść: https://opencredo.com/working-locally-with-microservices/ – MarkOfHall

+0

Wygląda artykułu tylko rozmowy na temat podstaw i jest napisany w języku wysokiego poziomu. Podejścia są dość oczywiste, bardziej mnie interesuje, jeśli ktoś znalazł dobry sposób na zrobienie tego. Wymieniona tutaj małpa kodowa ninja jest sposobem, ale to nadal wymaga od mnie inżynierii wstecznej i utrzymania "fałszywej eureki" ... –

Odpowiedz

5

Poniższy kod (zaczerpnięty z https://github.com/Netflix/eureka/blob/a7a8d278e6399bbff5faa49b9fcbcd7ea9e854f4/eureka-core/src/test/java/com/netflix/eureka/mock/MockRemoteEurekaServer.java) może być pomocny;

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); 
} 

} 
+1

W przyszłości nie wolno kopiować treści z innych źródeł bez wyraźnej atrybucji. Jest postrzegany jako plagiat. Zobacz http://stackoverflow.com/help/referencing – Matt

5

Jedną z opcji jest użycie Camela do podszywania się/zastępowania punktów końcowych Eureka. Powinna istnieć konfiguracja informująca twoją aplikację, gdzie szukać Eureka, więc zastąp to w konfiguracji testowej, aby wskazać nowy punkt końcowy.

Następnie stwórz trasę wielbłądzią w teście/src używając albo pomostu albo http, aby przedstawić ten nowy punkt końcowy, który zwróci odpowiedź, której oczekuje LoadBalancerClient. Ta odpowiedź będzie zawierać test URI (tzn. Twoją aplikację).

Powiązane problemy