使用反射为私有方法编写测试
Use Reflection to Write test for private methods
我有一个 class 即 NetworkManager
。我有很多 private
方法,我确实需要为它们编写测试。
起初我没有找到任何解决方案来为我的私有方法编写测试。无论如何,我找到了一种方法来访问我的私有方法并为它们编写一些测试。
我使用反射来访问我的函数并为它们编写测试。有一个简单的私有方法的例子:
private String myFun (String input){
return input+"hello";
}
有一个测试class,我在里面用到了反射:
@RunWith(AndroidJUnit4.class)
public class NetworkManagerTest {
private static NetworkManager networkManager;
private Context appContext = InstrumentationRegistry.getTargetContext();
private @ADType
int adType = ADType.TYPE_BANNER;
@BeforeClass
public static void setup() {
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
networkManager = NetworkManager.getInstance();
networkManager.addNetworkCall(TestUtil.getSampleSystemRequest());
}
});
}
@Test
public void sample() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = NetworkManager.class.getDeclaredMethod("myFun", String.class);
method.setAccessible(true);
String output = (String) method.invoke(networkManager, "Ehsan");
Assert.assertEquals("Ehsanhello", output);
}
}
这很好用。但问题是这种方式可以用反射编写私有方法测试多少?
有没有更好的方法来实现这个目标?
But the question is how much is this way okay to write test for private methods with using of reflection?
Is there a better way to achieve this goal?
最常见的方法是放弃该目标。
从历史上看,TDD 的重点一直是验证行为,而不是实现细节。部分要点是测试让我们可以自由地更改代码的内部设计,自信地,因为测试会提醒我们任何意外的行为更改。
因此,如果我们需要测试以确保某些私有方法中的逻辑是正确的,我们会为 public API 找到一个依赖于该逻辑的用例,并编写测试测量 public API.
的行为
我们可以通过在私有方法中注入临时错误来校准测试,并验证测试是否检测到错误。
完成之后,我们可以选择通过内联私有方法来重构代码;在这种情况下,所有测试仍应通过,因为我们没有改变测试对象的行为——我们只是移动了细节。
如果您打算积极改进应用程序的内部设计,那么您需要与该内部设计分离的测试。
我热衷于说如果你有太多的私有方法要测试,这意味着你的 class 有太多的责任。私有方法可以按逻辑分组并提取到其他 classes.
这就是我不接受 Guava 的 @VisibleForTesting
注释的原因。
我有一个 class 即 NetworkManager
。我有很多 private
方法,我确实需要为它们编写测试。
起初我没有找到任何解决方案来为我的私有方法编写测试。无论如何,我找到了一种方法来访问我的私有方法并为它们编写一些测试。
我使用反射来访问我的函数并为它们编写测试。有一个简单的私有方法的例子:
private String myFun (String input){
return input+"hello";
}
有一个测试class,我在里面用到了反射:
@RunWith(AndroidJUnit4.class)
public class NetworkManagerTest {
private static NetworkManager networkManager;
private Context appContext = InstrumentationRegistry.getTargetContext();
private @ADType
int adType = ADType.TYPE_BANNER;
@BeforeClass
public static void setup() {
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
networkManager = NetworkManager.getInstance();
networkManager.addNetworkCall(TestUtil.getSampleSystemRequest());
}
});
}
@Test
public void sample() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = NetworkManager.class.getDeclaredMethod("myFun", String.class);
method.setAccessible(true);
String output = (String) method.invoke(networkManager, "Ehsan");
Assert.assertEquals("Ehsanhello", output);
}
}
这很好用。但问题是这种方式可以用反射编写私有方法测试多少?
有没有更好的方法来实现这个目标?
But the question is how much is this way okay to write test for private methods with using of reflection?
Is there a better way to achieve this goal?
最常见的方法是放弃该目标。
从历史上看,TDD 的重点一直是验证行为,而不是实现细节。部分要点是测试让我们可以自由地更改代码的内部设计,自信地,因为测试会提醒我们任何意外的行为更改。
因此,如果我们需要测试以确保某些私有方法中的逻辑是正确的,我们会为 public API 找到一个依赖于该逻辑的用例,并编写测试测量 public API.
的行为我们可以通过在私有方法中注入临时错误来校准测试,并验证测试是否检测到错误。
完成之后,我们可以选择通过内联私有方法来重构代码;在这种情况下,所有测试仍应通过,因为我们没有改变测试对象的行为——我们只是移动了细节。
如果您打算积极改进应用程序的内部设计,那么您需要与该内部设计分离的测试。
我热衷于说如果你有太多的私有方法要测试,这意味着你的 class 有太多的责任。私有方法可以按逻辑分组并提取到其他 classes.
这就是我不接受 Guava 的 @VisibleForTesting
注释的原因。