1

我有一个 Spring Boot API,它使用 Spring WebClient 在内部调用两个 3rd 方 API。我需要通过模拟两个 API 调用来端到端地测试我的 API。如何创建一个 MockWebServer 来模拟 DAOImpl 类中的两个 API 调用。

我尝试配置一个 MockWebServer 来模拟 WebClient,但它不起作用。

我的控制器

@Autowired
private DemoDao dao;

@RequestMapping(value = "/webClient/testing", produces = { "application/json"}, method = RequestMethod.GET)
public ResponseEntity<String> webClientNonBlockingClient(@RequestHeader(value = "name_id", required = false) String nameId)
  {
    HttpStatus httpStatus = HttpStatus.OK;
    String userId = dao.getUserId(nameId);
    boolean userCheck = dao.checkUserAccess(nameId, userId);
    if (userCheck)
    {
      message = "check success";
    }
    else
    {
      message = "check failed";
      httpStatus = HttpStatus.UNAUTHORIZED;
    }
    return new ResponseEntity<>(message, httpStatus);
  }

DAO 实现类

@Repository
public class DemoDAOImpl
{

  @Autowired
  private WebClientFactory webClientFactory;

  public String getUserId(String nameId)
  {
    UserProfile profile = new UserProfile();
    Mono<UserProfile> response = null;
    try
    {
      String url = "/user/"+nameId+"/profile"
      WebClient client = webClientFactory.getWebClient();
      response = client.get().uri(builder -> 
      builder.path(url).build()).retrieve().bodyToMono(UserProfile.class);
      profile = response.block();
    }
    catch (WebClientResponseException e)
    {
      LOG.error("ResponseException {}", e);
    }
    return profile.getUserId();
  }
  
  public boolean userCheck(String nameId, String userId)
  {
    Mono<UserAccessResponse> result = null;
    try
    {
      WebClient client = webClientFactory.getWebClient();
      String url = "/user/"+nameId+"/check"
      result = client.get().uri(builder -> builder.path(url).queryParam("userId", userId).build())
          .retrieve().bodyToMono(UserAccessResponse.class);
      return result.block().isStatus();
    }
    catch (WebClientResponseException e)
    {
      LOG.error("APIexception {}", e);
    }
  }

webClient 配置类

@Configuration
public class WebClientFactory
{
  
  private String baseUrl = "https://abcd.com/v1/";
  
  private String apikey = "123456";
  
  public WebClientFactory()
  {
    // Default constructor
  }

  @Bean
  @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
  public WebClient getWebClient()
  {
    return WebClient
        .builder()
        .baseUrl(baseUrl)
        .defaultHeader(HttpHeaders.CONTENT_TYPE, 
 MediaType.APPLICATION_JSON_VALUE)
        .defaultHeader("apikey", apikey)
      .build();
  }  
}
}

我尝试使用以下测试类进行模拟,但它没有按预期工作。我无法配置如何模拟 2 个外部 api 调用。

测试班

@RunWith(SpringRunner.class)
@WebAppConfiguration()
@TestPropertySource("classpath:dev-manifest.yml")
@ContextConfiguration(classes = Application.class)
@SpringBootTest
public class WebClientMockTesting
{

  private static final Logger logger = LoggerFactory.getLogger(WebClientMockTesting.class);

  private static final String REQUEST_URI = "/webClient/testing";
  private static final String HEADER_KEY = "name_id";
  private static final String MOCK_USER_ID = "mockTest";

  private final MockWebServer mockWebServer = new MockWebServer();

  @Autowired
  private WebClientFactory webClientFactory;

  @Autowired
  private WebClient webClient;

  private MockMvc mockMvc;

  @Autowired
  private WebApplicationContext webApplicationContext;

  /**
   * build web application context
   */
  @Before
  public void setup()
  {
    try
    {
      mockWebServer.play(8084);
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
    webClient = webClientFactory.getWebClient();
    webClient = WebClient.create(mockWebServer.getUrl("/").toString());
    this.mockMvc = webAppContextSetup(webApplicationContext).build();
  }

  @AfterEach
  void tearDown() throws IOException
  {
    mockWebServer.shutdown();
  }

  /**
   * Success scenario - GetFutureProjectedIncomeRIC
   */
  @Test
  public void testGetId()
  {
    try
    {
      mockWebServer.enqueue(
          new MockResponse()
                  .setResponseCode(200)
                  .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                  .setBody("{\"y\": \"value for y\", \"z\": 789}")
  );

      mockMvc.perform(get(REQUEST_URI).contentType(contentType).header(HEADER_KEY, MOCK_USER_ID))
          .andExpect(status().isOk());
    }
    catch (Exception e)
    {
      logger.error("test failed due to - {}", e.getStackTrace());
    }
  }
4

1 回答 1

0

究竟是什么行不通?在模拟 Web 服务器中,您创建一个响应队列,按照添加它们的顺序一一发回。在您的代码中,您使用添加一个响应

mockWebServer.enqueue(

如果您需要从您的应用程序进行 3 次调用,则应调用 enqueue 3 次。

于 2019-08-18T03:22:04.593 回答