使用mockitotesting私有方法

公开课A {

     public void method(boolean b){
          如果(b ==真)
               方法1();
          其他
               方法2();
     }

     private void method1(){}
     private void method2(){}
 }
公共类TestA {

     @testing
     public void testMethod(){
       A =模拟(A.class);
       a.method(真);
       //如何validation(a).method1();
     }
 }

如何testing私有方法是否被调用,以及如何testing私有方法使用mockito?

你不能用Mockito做到这一点,但你可以使用Powermock来扩展Mockito和模拟私有方法。 Powermock支持Mockito。 这是一个例子。

不可以通过mockito。 从他们的维基

为什么Mockito不嘲笑私人方法?

首先,我们不是嘲笑私人方法的教条。 我们不关心私有方法,因为从testing的angular度来看私有方法是不存在的。 这里有几个原因Mockito不嘲笑私人方法:

它需要对类加载器进行黑客攻击,而且它会改变API(您必须使用自定义testing运行器,注释类等)。

要解决这个问题非常容易 – 只需要将方法的可见性从私有方法改为受封装保护(或保护)即可。

这需要我花时间来实施和维护它。 在第二点和它已经在不同的工具(powermock)中实现的事实是没有意义的。

最后…嘲笑私有方法暗示OO理解有问题。 在OO中,您需要对象(或angular色)进行协作,而不是方法。 忘记pascal和程序代码。 在对象中思考。

这里是一个小例子,如何与powermock做到这一点

public class Hello { private Hello obj; private Integer method1(Long id) { return id + 10; } } 

要testingmethod1使用代码:

 Hello testObj = new Hello(); Integer result = Whitebox.invokeMethod(testObj, "method1", new Long(10L)); 

要设置私人对象obj使用这个:

 Hello testObj = new Hello(); Hello newObject = new Hello(); Whitebox.setInternalState(testObj, "obj", newObject); 

从行为的angular度思考这个问题,而不是用什么方法。 如果b为真,则称为method具有特定的行为。 如果b是假的,它有不同的行为。 这意味着你应该为method写两个不同的testing; 每个案件一个。 因此,不是有三个面向方法的testing(一个用于method ,一个用于method1 ,另一个用于method2 ,则有两个面向行为的testing。

与此相关(我最近在另一个SO线程中提出了这个问题,结果被称为一个四个字母的单词,所以随便拿一粒盐)。 我发现select反映我正在testing的行为的testing名称是有帮助的,而不是方法的名称。 所以不要调用你的testingtestMethod()testMethod1()testMethod2()等等。 我喜欢像calculatedPriceIsBasePricePlusTax()taxIsExcludedWhenExcludeIsTrue()这样的名称,它们表示我正在testing什么行为; 那么在每个testing方法中,只testing指定的行为。 大多数这样的行为只涉及到一个公共方法的调用,但可能涉及很多私人方法的调用。

希望这可以帮助。

你不是想testing私有方法。 只有非私有方法需要testing,因为它们应该调用私有方法。 如果你“想”testing私有方法,这可能表明你需要重新考虑你的devise:

我使用适当的dependency injection? 我可能需要将私有方法移动到一个单独的类,而是testing? 这些方法必须是私人的吗? …他们不能默认或保护呢?

在上面的例子中,被称为“随机”的两个方法可能实际上需要放在他们自己的一个类中,然后被testing,然后注入到上面的类中。

我真的不明白你需要testing私有方法。 根本问题是你的公共方法作为返回types是无效的,因此你不能testing你的公共方法。 因此你被迫testing你的私有方法。 我的猜测是正确的吗?

一些可能的解决scheme(AFAIK):

  1. 嘲笑你的私人方法,但你仍然不会“实际”testing你的方法。

  2. validation方法中使用的对象的状态。 MOSTLY方法要么对input值进行一些处理,要么返回输出,要么改变对象的状态。 也可以使用testing对象的期望的状态。

     public class A{ SomeClass classObj = null; public void publicMethod(){ privateMethod(); } private void privateMethod(){ classObj = new SomeClass(); } } 

    [在这里你可以testing私有方法,通过检查classObj的状态从null变为非null。]

  3. 重构你的代码(希望这不是遗留代码)。 我写一个方法的基础是,应该总是返回一些东西(一个int /一个布尔值)。 返回的值可能不会被实现使用,但是它肯定会被testing使用

    码。

     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() {} } 

我能够使用reflection来testing使用mockito的私有方法。 这里是例子,试图命名它是有道理的

 //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)); 

把你的testing放在同一个软件包中,但不同的源文件夹(src / main / java与src / test / java),并使这些方法为package-private。 Imo的可testing性比隐私更重要。