Можем ли мы заглушить в Spring Boot Test, Mockito или powerMock таким же образом, как с Wiremock - PullRequest
0 голосов
/ 27 января 2020

Действительно, Wiremock очень мощный, что касается интеграционных тестов. Мне нравится, как Wiremock заглушает ответ URL без мутации бобов (как мы делаем в mockito или powermock для юнит-тестов).

    @Mock
    SomeRepository someRepository; //Zombie mutation

    @Mock
    AnotherComponent anotherComponent; //mutation

    @InjectMocks
    SomeService someService; //mutation - This is the class we are unit testing

В интеграционном тесте я хочу, чтобы все 3 слоя были пройти тестирование и смоделировать внешнюю зависимость

                      +---> Repository -----> MySQL (I managed this with in-memory h2 database)
                      |
controller---> service 
                      | 
                      +---> Proxy ---------> Another REST service (some way to mock the call???)

Можно ли сделать то же самое с помощью Spring Boot Test, или mockito или powermock (так как я их уже использую и просто не хочу добавлять новую библиотеку в проект)

Вот как мы делаем заглушки в Wiremock.

 service.stubFor(get(urlEqualTo("/another/service/call"))
                .willReturn(jsonResponse(toJson(objResponse))));

Над кодом означает, что в нашем тесте всякий раз, когда вызывается внешняя служба (* 1015) *), он будет перехвачен и будет введен пример ответа - и внешний вызов не покинет систему

Пример кода

@SpringBootTest
@AutoConfigureMockMvc
public class StubTest {
    @Autowired
    private MockMvc mockMvc;

    private MockRestServiceServer server;

    @BeforeEach
    public void init() {
        RestTemplate restTemplate = new RestTemplate();
        server = MockRestServiceServer.bindTo(restTemplate).build();
    }

    @Test
    public void testFakeLogin() throws Exception {
        String sampleResponse = stubSampleResponse();

        //Actual URL to test
        String result = mockMvc.perform(get("/s1/method1")
                .contentType("application/json"))
                .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();

        assertThat(result).isNotNull();
        assertThat(result).isEqualTo(sampleResponse);
    }

    private String stubSampleResponse() {

        String response = "Here is response";

        //URL to stub (this is in another service)
        server.expect(requestTo("/v1/s2/dependent-method"))
                .andExpect(method(HttpMethod.GET))
                .andRespond(withSuccess(response, MediaType.APPLICATION_JSON));

        return response;
    }
}

Feign Client

@FeignClient(value = "service-s2", url = "http://localhost:8888/")
public interface S2Api {
    @GetMapping("/v1/s2/dependent-method")
    public String dependentMethod();
}

, но я получаю следующую ошибку, которая означает, что этот URL не был заглушен.

feign.RetryableException: Connection refused: connect executing GET http://localhost:8888/v1/s2/dependent-method
    at feign.FeignException.errorExecuting(FeignException.java:213) ~[feign-core-10.4.0.jar:na]

1 Ответ

1 голос
/ 27 января 2020

Да, возможно с MockRestServiceServer.

Пример:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.boot.test.autoconfigure.web.client.AutoConfigureWebClient;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;

@RunWith(SpringRunner.class)
@RestClientTest(MyRestClient.class)
@AutoConfigureWebClient(registerRestTemplate = true)
public class MyRestClientTest {
    @Autowired
    private MockRestServiceServer server;

    @Test
    public void getInfo() {
        String response = "response";
        server.expect(requestTo("http://localhost:8090" + "/another/service/call"))
            .andExpect(method(HttpMethod.GET))
            .andRespond(withSuccess(response,MediaType.APPLICATION_JSON));
    }
}
...