我有一个 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());
}
}