用 mockito 模拟 Unirest
Mocking Unirest with mockito
我正处于开始编程阶段,我想询问有关使用 Mockito 模拟对象的问题,更具体地说是 Unirest 响应。
假设我有一个数据库,每次测试时我都不想打扰它,我想为此使用 Mockito,但问题是我不确定如何创建假的 "httpResponse" 对象回来。
为了提供一些背景信息,我附上了我的代码:
/**
* This method lists the ID of the activity when requested.
*
* @return the list of all activities
*/
public JSONArray getActivites() {
HttpResponse<JsonNode> jsonResponse = null;
try {
jsonResponse = Unirest
.get("http://111.111.111.111:8080/activity")
.header("accept", "application/json")
.asJson();
} catch (UnirestException e) {
System.out.println("Server is unreachable");
}
JSONArray listOfActivities = jsonResponse.getBody().getArray();
return listOfActivities;
}
所以我的想法是模拟 Unirest,然后当 .get 方法被调用时,我会 return 一个假的 HttpResponse,问题是,我不知道该怎么做,我有在网上看,并不能真正理解它。
是否可以使用实际数据库执行 1 次,然后 "Extract" 信息并每次都使用它进行测试?
使用 PowerMockRunner、PowerMockito 和 Mockito 的示例片段
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Unirest.class})
public class TestApp{
@Before
public void setup() {
PowerMockito.mockStatic(Unirest.class);
}
@Test
public void shouldTestgetActivites() throws UnirestException {
when(Unirest.get(Client.DEFAULT_BASE_URL)).thenReturn(getRequest);
when(getRequest.asJson()).thenReturn(httpResponse);
when(httpResponse.getStatus()).thenReturn(Integer.valueOf(200));
assertThat(something).isEqualTo(true);
}
}
您可以将调用包装在包装器 class 中,而不是直接调用静态成员,该包装器可以提供基于某些参数的 HttpResponse。这是一个可以在 Mockito 中轻松模拟的接口。
/**
* This is a wrapper around a Unirest API.
*/
class UnirestWrapper {
private HttpResponse<JsonNode> getResponse(String accept, String url) {
try {
return Unirest
.get(url)
.header("accept", accept)
.asJson();
} catch (UnirestException e) {
System.out.println("Server is unreachable");
}
// Or create a NULL HttpResponse instance.
return null;
}
}
private final UnirestWrapper unirestWrapper;
ThisClassConstructor(UnirestWrapper unirestWrapper) {
this.unirestWrapper = unirestWrapper;
}
/**
* This method lists the ID of the activity when requested.
*
* @return the list of all activities
*/
public JSONArray getActivites() {
HttpResponse<JsonNode> jsonResponse = this.unirestWrapper.getResponse("http://111.111.111.111:8080/activity", "application/json");
if (jsonResponse == null) {
return null;
}
JSONArray listOfActivities = jsonResponse.getBody().getArray();
return listOfActivities;
}
或者您可以使用电源模拟...
与此同时,原作者通过 unirest-mocks:
提供模拟支持
行家:
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-mocks</artifactId>
<version>LATEST</version>
<scope>test</scope>
</dependency>
用法:
class MyTest {
@Test
void expectGet(){
MockClient mock = MockClient.register();
mock.expect(HttpMethod.GET, "http://zombo.com")
.thenReturn("You can do anything!");
assertEquals(
"You can do anything!",
Unirest.get("http://zombo.com").asString().getBody()
);
//Optional: Verify all expectations were fulfilled
mock.verifyAll();
}
}
您可以使用 Mockito.mock(HttpResponse.class)
模拟 HttpResponse
并在获取此响应的正文时放入您的 json。例如:
HttpResponse response = Mockito.mock(HttpResponse.class);
when(response.getBody()).thenReturn(readFileContent("my_response.json"));
此 'readFileContent' 只是一种读取我放置回复的文件的方法。你可以把你的 json 放在那里比较
我使用 JUnit5 和 Mockito 解决了类似的任务。
Class 正在测试中:
@Service
@RequiredArgsConstructor
@Profile("someProfile")
@Slf4j
public class SomeService {
@Value("${value1}")
private final String value1;
@Value("${value2}")
private final String value2;
private final ObjectMapper mapper;
private final CommonUtil commonUtil;
public boolean methodUnderTest(String inputValue) {
HttpResponse<String> result;
//some logic
try {
result = Unirest.get("url")
.header(header, value)
.routeParam("param", paramValue)
.asString();
if (result.getStatus() != 200) {
throw new MyException("Message");
}
//some logic
} catch (Exception e) {
log.error("Log error", e);
//some logic
}
}
}
并测试:
@ExtendWith(MockitoExtension.class)
class SomeServiceTest {
@Mock
private CommonUtil commonUtil;
@Mock
private ObjectMapper mapper;
@Mock
HttpResponse httpResponse;
@Mock
GetRequest request;
private SomeService serviceUnderTest;
@BeforeEach
void setUp() {
this.serviceUnderTest = new SomeService("url", "valu1", mapper, commonUtil);
}
@Test
void methodUnderTest_whenSmth_ThenSmth() throws UnirestException {
try (MockedStatic<Unirest> unirest = Mockito.mockStatic(Unirest.class)) {
unirest.when(() -> Unirest.get(anyString()))
.thenReturn(request);
Mockito.when(commonUtil.encodeValue(Mockito.anyString())).thenReturn("123");
Mockito.when(request.header(anyString(), anyString())).thenReturn(request);
Mockito.when(request.routeParam(anyString(), anyString())).thenReturn(request);
Mockito.when(request.asString()).thenReturn(httpResponse);
Mockito.when(httpResponse.getStatus()).thenReturn(200);
Mockito.when(httpResponse.getBody()).thenReturn("true");
assertTrue(serviceUnderTest.methodUnderTest("123"));
}
}
}
我正处于开始编程阶段,我想询问有关使用 Mockito 模拟对象的问题,更具体地说是 Unirest 响应。 假设我有一个数据库,每次测试时我都不想打扰它,我想为此使用 Mockito,但问题是我不确定如何创建假的 "httpResponse" 对象回来。 为了提供一些背景信息,我附上了我的代码:
/**
* This method lists the ID of the activity when requested.
*
* @return the list of all activities
*/
public JSONArray getActivites() {
HttpResponse<JsonNode> jsonResponse = null;
try {
jsonResponse = Unirest
.get("http://111.111.111.111:8080/activity")
.header("accept", "application/json")
.asJson();
} catch (UnirestException e) {
System.out.println("Server is unreachable");
}
JSONArray listOfActivities = jsonResponse.getBody().getArray();
return listOfActivities;
}
所以我的想法是模拟 Unirest,然后当 .get 方法被调用时,我会 return 一个假的 HttpResponse,问题是,我不知道该怎么做,我有在网上看,并不能真正理解它。 是否可以使用实际数据库执行 1 次,然后 "Extract" 信息并每次都使用它进行测试?
使用 PowerMockRunner、PowerMockito 和 Mockito 的示例片段
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Unirest.class})
public class TestApp{
@Before
public void setup() {
PowerMockito.mockStatic(Unirest.class);
}
@Test
public void shouldTestgetActivites() throws UnirestException {
when(Unirest.get(Client.DEFAULT_BASE_URL)).thenReturn(getRequest);
when(getRequest.asJson()).thenReturn(httpResponse);
when(httpResponse.getStatus()).thenReturn(Integer.valueOf(200));
assertThat(something).isEqualTo(true);
}
}
您可以将调用包装在包装器 class 中,而不是直接调用静态成员,该包装器可以提供基于某些参数的 HttpResponse。这是一个可以在 Mockito 中轻松模拟的接口。
/**
* This is a wrapper around a Unirest API.
*/
class UnirestWrapper {
private HttpResponse<JsonNode> getResponse(String accept, String url) {
try {
return Unirest
.get(url)
.header("accept", accept)
.asJson();
} catch (UnirestException e) {
System.out.println("Server is unreachable");
}
// Or create a NULL HttpResponse instance.
return null;
}
}
private final UnirestWrapper unirestWrapper;
ThisClassConstructor(UnirestWrapper unirestWrapper) {
this.unirestWrapper = unirestWrapper;
}
/**
* This method lists the ID of the activity when requested.
*
* @return the list of all activities
*/
public JSONArray getActivites() {
HttpResponse<JsonNode> jsonResponse = this.unirestWrapper.getResponse("http://111.111.111.111:8080/activity", "application/json");
if (jsonResponse == null) {
return null;
}
JSONArray listOfActivities = jsonResponse.getBody().getArray();
return listOfActivities;
}
或者您可以使用电源模拟...
与此同时,原作者通过 unirest-mocks:
提供模拟支持行家:
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-mocks</artifactId>
<version>LATEST</version>
<scope>test</scope>
</dependency>
用法:
class MyTest {
@Test
void expectGet(){
MockClient mock = MockClient.register();
mock.expect(HttpMethod.GET, "http://zombo.com")
.thenReturn("You can do anything!");
assertEquals(
"You can do anything!",
Unirest.get("http://zombo.com").asString().getBody()
);
//Optional: Verify all expectations were fulfilled
mock.verifyAll();
}
}
您可以使用 Mockito.mock(HttpResponse.class)
模拟 HttpResponse
并在获取此响应的正文时放入您的 json。例如:
HttpResponse response = Mockito.mock(HttpResponse.class);
when(response.getBody()).thenReturn(readFileContent("my_response.json"));
此 'readFileContent' 只是一种读取我放置回复的文件的方法。你可以把你的 json 放在那里比较
我使用 JUnit5 和 Mockito 解决了类似的任务。 Class 正在测试中:
@Service
@RequiredArgsConstructor
@Profile("someProfile")
@Slf4j
public class SomeService {
@Value("${value1}")
private final String value1;
@Value("${value2}")
private final String value2;
private final ObjectMapper mapper;
private final CommonUtil commonUtil;
public boolean methodUnderTest(String inputValue) {
HttpResponse<String> result;
//some logic
try {
result = Unirest.get("url")
.header(header, value)
.routeParam("param", paramValue)
.asString();
if (result.getStatus() != 200) {
throw new MyException("Message");
}
//some logic
} catch (Exception e) {
log.error("Log error", e);
//some logic
}
}
}
并测试:
@ExtendWith(MockitoExtension.class)
class SomeServiceTest {
@Mock
private CommonUtil commonUtil;
@Mock
private ObjectMapper mapper;
@Mock
HttpResponse httpResponse;
@Mock
GetRequest request;
private SomeService serviceUnderTest;
@BeforeEach
void setUp() {
this.serviceUnderTest = new SomeService("url", "valu1", mapper, commonUtil);
}
@Test
void methodUnderTest_whenSmth_ThenSmth() throws UnirestException {
try (MockedStatic<Unirest> unirest = Mockito.mockStatic(Unirest.class)) {
unirest.when(() -> Unirest.get(anyString()))
.thenReturn(request);
Mockito.when(commonUtil.encodeValue(Mockito.anyString())).thenReturn("123");
Mockito.when(request.header(anyString(), anyString())).thenReturn(request);
Mockito.when(request.routeParam(anyString(), anyString())).thenReturn(request);
Mockito.when(request.asString()).thenReturn(httpResponse);
Mockito.when(httpResponse.getStatus()).thenReturn(200);
Mockito.when(httpResponse.getBody()).thenReturn("true");
assertTrue(serviceUnderTest.methodUnderTest("123"));
}
}
}