Nag*_*ran 90 java junit mockito
public class A { public void method(boolean b){ if (b == true) method1(); else method2(); } private void method1() {} private void method2() {} }
public class TestA { @Test public void testMethod() { A a = mock(A.class); a.method(true); //how to test like verify(a).method1(); } }
如何测试私有方法是否被调用,以及如何使用mockito测试私有方法???
Ara*_*ram 125
不可能通过mockito.来自他们的维基
为什么Mockito不会模仿私有方法?
首先,我们对于嘲弄私人方法不是教条主义.我们只是不关心私有方法,因为从测试私有方法的角度来看不存在.以下是Mockito不会模仿私有方法的几个原因:
它需要对类加载器进行黑客攻击,这种类加载器绝不是防弹的,它会改变api(你必须使用自定义测试运行器,注释类等).
这很容易解决 - 只需将方法的可见性从私有更改为受包保护(或受保护).
它需要我花时间实施和维护它.鉴于第2点和它已经在不同的工具(powermock)中实现的事实,它没有意义.
最后......嘲弄私有方法暗示OO理解存在问题.在OO中,您希望对象(或角色)进行协作,而不是方法.忘记pascal和程序代码.在对象中思考.
Min*_*nas 31
这是一个如何用powermock做的小例子
public class Hello {
private Hello obj;
private Integer method1(Long id) {
return id + 10;
}
}
Run Code Online (Sandbox Code Playgroud)
要测试method1,请使用代码:
Hello testObj = new Hello();
Integer result = Whitebox.invokeMethod(testObj, "method1", new Long(10L));
Run Code Online (Sandbox Code Playgroud)
要设置私有对象obj,请使用以下命令:
Hello testObj = new Hello();
Hello newObject = new Hello();
Whitebox.setInternalState(testObj, "obj", newObject);
Run Code Online (Sandbox Code Playgroud)
Daw*_*ica 16
从行为的角度考虑这一点,而不是根据哪些方法.method
如果b
为true,则调用的方法具有特定行为.如果b
是假的,它有不同的行为.这意味着你应该写两个不同的测试method
; 每个案例一个.因此,不是有三个面向方法的测试(一个用于method
,一个用于method1
,一个用于method2
,你有两个面向行为的测试.
与此相关(我最近在另一个SO线程中提出了这个问题,因此得到了一个四个字母的单词,所以请随意拿出一些盐); 我发现选择反映我正在测试的行为的测试名称是有帮助的,而不是方法的名称.所以,不要打电话给你测试testMethod()
,testMethod1()
,testMethod2()
等等.我喜欢这样的名字,calculatedPriceIsBasePricePlusTax()
或者taxIsExcludedWhenExcludeIsTrue()
表示我正在测试的行为; 然后在每个测试方法中,仅测试指示的行为.大多数此类行为仅涉及对公共方法的一次调用,但可能涉及对私有方法的多次调用.
希望这可以帮助.
Sin*_*run 13
通过使用反射,可以从测试类调用私有方法。在这种情况下,
//测试方法会是这样的...
public class TestA {
@Test
public void testMethod() {
A a= new A();
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
// invoke the private method for test
privateMethod.invoke(A, null);
}
}
Run Code Online (Sandbox Code Playgroud)如果私有方法调用任何其他私有方法,那么我们需要监视对象并存根另一个方法。测试类将类似于......
//测试方法会是这样的...
public class TestA {
@Test
public void testMethod() {
A a= new A();
A spyA = spy(a);
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
doReturn("Test").when(spyA, "method2"); // if private method2 is returning string data
// invoke the private method for test
privateMethod.invoke(spyA , null);
}
}
Run Code Online (Sandbox Code Playgroud)**方法是结合反射和窥探对象。**method1 和 **method2 是私有方法,method1 调用 method2。
你不应该测试私有方法.只需要测试非私有方法,因为这些方法应该调用私有方法.如果您"想"测试私有方法,则可能表明您需要重新考虑您的设计:
我使用适当的依赖注入吗?我是否可能需要将私有方法移动到单独的类中而是测试它?这些方法必须是私有的吗?......他们不能默认或保护吗?
在上面的例子中,两个被称为"随机"的方法实际上可能需要放在他们自己的类中,测试然后注入上面的类.
虽然Mockito不提供该功能,但是您可以使用Mockito + JUnit ReflectionUtils类或Spring ReflectionTestUtils类来获得相同的结果。请参阅下面取自例如这里解释如何调用私有方法:
ReflectionTestUtils.invokeMethod(student, "saveOrUpdate", "From Unit test");
Run Code Online (Sandbox Code Playgroud)
可以在《Mockito for Spring》一书中找到ReflectionTestUtils和Mockito的完整示例。
我真的不明白您需要测试私有方法。根本问题是您的公共方法的返回类型为 void,因此您无法测试您的公共方法。因此,您被迫测试您的私有方法。我的猜测正确吗??
一些可能的解决方案(AFAIK):
嘲笑您的私有方法,但您仍然不会“实际”测试您的方法。
验证方法中使用的对象的状态。大多数方法要么对输入值进行一些处理并返回输出,要么更改对象的状态。也可以使用针对期望状态测试对象。
Run Code Online (Sandbox Code Playgroud)public class A{ SomeClass classObj = null; public void publicMethod(){ privateMethod(); } private void privateMethod(){ classObj = new SomeClass(); } }
[在这里你可以测试私有方法,通过检查 classObj 从空到非空的状态变化。]
稍微重构您的代码(希望这不是遗留代码)。我编写方法的基础是,一个人应该总是返回一些东西(一个整数/一个布尔值)。返回值可能或可能不会被实现使用,但它肯定会被测试使用
代码。
public class A
{
public int method(boolean b)
{
int nReturn = 0;
if (b == true)
nReturn = method1();
else
nReturn = method2();
}
private int method1() {}
private int method2() {}
}
Run Code Online (Sandbox Code Playgroud)我能够使用反射使用嘲笑来测试内部的私有方法。这是示例,尝试命名为有意义
//Service containing the mock method is injected with mockObjects
@InjectMocks
private ServiceContainingPrivateMethod serviceContainingPrivateMethod;
//Using reflection to change accessibility of the private method
Class<?>[] params = new Class<?>[]{PrivateMethodParameterOne.class, PrivateMethodParameterTwo.class};
Method m = serviceContainingPrivateMethod .getClass().getDeclaredMethod("privateMethod", params);
//making private method accessible
m.setAccessible(true);
assertNotNull(m.invoke(serviceContainingPrivateMethod, privateMethodParameterOne, privateMethodParameterTwo).equals(null));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
275106 次 |
最近记录: |