我编写了一个简单的方法,该方法应该使用url并通过get请求从此url中检索数据。该方法如下所示:
public String getResponse(String connectionUrl) throws HttpException {
HttpURLConnection connection = null;
try {
URL url = new URL(connectionUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
throw new HttpException("Response code was " + responseCode + " (should be 200)");
}
Scanner scanner = new Scanner(connection.getInputStream()).useDelimiter("\\A");
String response = scanner.hasNext() ? scanner.next() : "";
connection.disconnect();
scanner.close();
return response;
} catch (IOException e) {
if (connection != null) {
connection.disconnect();
}
throw new HttpException(e.getMessage(), e.getCause());
}
}
现在我正在为这种方法编写单元测试。我使用PowerMock与Mockito和JUnit编写我的测试。有问题的测试看起来像这样:
@Test
public void getResponse_NormalResponse() throws Exception {
String expectedResponse = "This is the expected response text!";
URL url = PowerMockito.mock(URL.class);
HttpURLConnection connection = PowerMockito.mock(HttpURLConnection.class);
InputStream inputStream = PowerMockito.mock(InputStream.class);
Scanner scanner = PowerMockito.mock(Scanner.class);
PowerMockito.whenNew(URL.class).withArguments(REQUEST_URL).thenReturn(url);
PowerMockito.whenNew(Scanner.class).withArguments(inputStream).thenReturn(scanner);
PowerMockito.when(url.openConnection()).thenReturn(connection);
// Response code mocked here
PowerMockito.when(connection.getResponseCode()).thenReturn(200);
PowerMockito.when(connection.getInputStream()).thenReturn(inputStream);
PowerMockito.when(scanner.hasNext()).thenReturn(true);
PowerMockito.when(scanner.next()).thenReturn(expectedResponse);
HttpClient httpClient = new HttpClient();
String actualResponse = httpClient.getResponse(REQUEST_URL);
Assert.assertEquals("Response is wrong!", expectedResponse, actualResponse);
}
但是当我运行测试时,会抛出HttpException,因为响应代码是404.测试是使用PowerMockRunner运行的。我做错了什么,为什么这个测试没有正常工作?
答案 0 :(得分:1)
你必须在@PrepareForTest下添加创建新对象的类,因为你正在使用whenNew。
你的班级似乎是HttpClient
@PrepareForTest({ URL.class, Scanner.class ,HttpClient.class})
解决了测试中的另一个问题。 添加了缺失的期望。
PowerMockito.when(scanner.useDelimiter("\\A")).thenReturn(scanner);
更正了工作代码:
来源:
public class HttpClient {
public String getResponse(String connectionUrl) throws HttpException {
HttpURLConnection connection = null;
try {
URL url = new URL(connectionUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
throw new HttpException("Response code was " + responseCode
+ " (should be 200)");
}
Scanner scanner = new Scanner(connection.getInputStream())
.useDelimiter("\\A");
String response = scanner.hasNext() ? scanner.next() : "";
connection.disconnect();
scanner.close();
return response;
} catch (IOException e) {
if (connection != null) {
connection.disconnect();
}
throw new HttpException(e.getMessage(), e.getCause());
}
}
}
class HttpException extends Exception {
public HttpException(String string) {
super(string);
}
public HttpException(String message, Throwable cause) {
super(message, cause);
}
}
测试用例:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ URL.class, Scanner.class, HttpClient.class })
public class HttpClientTest {
private static final String REQUEST_URL = "http://wwww.google.com";
@Test
public void getResponse_NormalResponse() throws Exception {
String expectedResponse = "This is the expected response text!";
URL url = PowerMockito.mock(URL.class);
HttpURLConnection connection = PowerMockito
.mock(HttpURLConnection.class);
InputStream inputStream = PowerMockito.mock(InputStream.class);
Scanner scanner = PowerMockito.mock(Scanner.class);
PowerMockito.whenNew(URL.class).withArguments(REQUEST_URL)
.thenReturn(url);
PowerMockito.whenNew(Scanner.class).withArguments(inputStream)
.thenReturn(scanner);
PowerMockito.when(scanner.useDelimiter("\\A")).thenReturn(scanner);
PowerMockito.when(url.openConnection()).thenReturn(connection);
// Response code mocked here
PowerMockito.when(connection.getResponseCode()).thenReturn(200);
PowerMockito.when(connection.getInputStream()).thenReturn(inputStream);
PowerMockito.when(scanner.hasNext()).thenReturn(true);
PowerMockito.when(scanner.next()).thenReturn(expectedResponse);
HttpClient httpClient = new HttpClient();
String actualResponse = httpClient.getResponse(REQUEST_URL);
Assert.assertEquals("Response is wrong!", expectedResponse,
actualResponse);
}
}
附上我用过的pom。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>MockItToExample</groupId>
<artifactId>MockItToExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.3</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
答案 1 :(得分:0)
使用以下命令注释您的测试类:
@PrepareForTest({URL.class, Scanner.class})
当您想要模拟对象创建时(对于使用whenNew
的每个类),您需要为每种情况添加它。