unit-testing - 如何模拟在另一个私有方法中调用的私有方法
问题描述
我试图模拟一个私有方法的输出,该输出在另一个私有方法中被调用,我别无选择,只能测试后面的私有方法,所以我添加了我可以在这里表示的示例测试代码,
这个示例类
package com.testableClass;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class TestableClass {
private int initialMockMethod(Object obj)
{
System.out.println(" ++++ Came Here ++++ ");
String str = getRestString("");
System.out.println("str ="+str);
return str.length();
}
private String getRestString(String abc)
{
String output="";
try {
URL url = new URL("https://gorest.co.in/public-api/users");//your url i.e fetch data from .
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP Error code : "
+ conn.getResponseCode());
}
InputStreamReader in = new InputStreamReader(conn.getInputStream());
BufferedReader br = new BufferedReader(in);
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
return output;
} catch (Exception e) {
System.out.println("Exception in NetClientGet:- " + e);
}
return abc;
}
}
现在这个 PowerMock 类
package com.testableClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import junit.framework.Assert;
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.testableClass.TestableClass")
public class PowerMockTest {
@Test
public void testPrivateMethod() throws Exception
{
String message = "Hello PowerMockito";
String expectation = "Expectation";
TestableClass mock = PowerMockito.spy(new TestableClass());
// PowerMockito.doReturn(expectation).when(mock, "getRestString", message);
PowerMockito.when(mock, "getRestString", message).thenReturn(expectation);
int count = Whitebox.invokeMethod(mock, "initialMockMethod", new Object());
System.out.println(" +++ Count : "+count+" ++++ ");
Assert.assertTrue(true);
}
}
我的问题是当我运行我的测试用例时
PowerMockito.when(mock, "getRestString", message).thenReturn(expectation);
执行原始方法并返回原始输出,而我的要求是,当我的测试用例实际上调用私有方法initialMockMethod时,它不应该调用getRestString而不是它应该返回我的模拟预期输出,即“期望”
解决方案
我想说不要尝试模拟私有方法,而不是使用反射和 PowerMock。这是班级的一个隐藏细节。
我的建议是,如果您的方法发出 HTTP 请求,那么就让它这样做。但是您可以使用模拟服务器来模拟响应。但要做到这一点,您需要将端点设为外部,以便可以注入。
我稍微改变了你的班级;仍然是相同的目的。
public class TestableClass {
private final String resourceUrl;
public TestableClass(String resourceUrl) {
this.resourceUrl = resourceUrl;
}
public int publicMethod() {
return initialMockMethod(null);
}
private int initialMockMethod(Object obj) {
var str = getRestString("");
return str.length();
}
private String getRestString(String abc) {
try {
var url = new URL(resourceUrl);
var conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP Error code : "
+ conn.getResponseCode());
}
var in = new InputStreamReader(conn.getInputStream());
var br = new BufferedReader(in);
var result = br.lines().collect(Collectors.joining("\n"));
conn.disconnect();
return result;
} catch (Exception e) {
System.out.println("Exception in NetClientGet:- " + e);
}
return abc;
}
}
这是测试
public class TestingTestableClass {
@Test
@SneakyThrows
public void test() {
final var server = new MockWebServer();
server.start(9999);
var instance = new TestableClass("http://127.0.0.1:9999");
server.enqueue(
new MockResponse()
.setResponseCode(200)
.setBody("this is the response")
);
final int result = instance.publicMethod();
Assertions.assertEquals(
"this is the response".length(),
result
);
final var record = server.takeRequest();
final var method = record.getMethod();
Assertions.assertEquals("GET", method);
server.shutdown();
}
}
在这里查看 MockWebServer
推荐阅读
- git - 如何 - 将 git 移动到另一台计算机
- python-3.x - 执行控制台功能并同时运行 Tkinter GUI
- javascript - 如何将 .env 值从根组件项目共享到多个可重用的 npm 安装组件
- c++ - 在字符串的每个单词的末尾插入一个字符串
- stripe-payments - Stripe Checkout V3 是否提供某种“不完整”付款意图的自动取消?
- reactjs - React Leaflet Offline - 保存按钮组件
- haskell - 关于转换为浮点数的 Haskell 类型问题
- javascript - 如何在边缘浏览器中调整图像亮度
- javascript - 无法理解 Javascript 中日期时间的令人困惑的行为
- java - 在 JPA 中使用数组进行本机查询