uso unitarios test mock examples example ejemplo java junit mockito

java - unitarios - Prueba de método privado usando mockito



test unitarios java mockito (8)

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

¿Cómo se prueba o no el método privado, y cómo probar el método privado usando mockito?


Aquí hay un pequeño ejemplo de cómo hacerlo con Powermock

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

Para probar el método 1 use el código:

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

Para establecer obj de objeto privado, use esto:

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


No es posible a través de mockito. De su wiki

¿Por qué Mockito no se burla de los métodos privados?

En primer lugar, no somos dogmáticos al burlarnos de los métodos privados. Simplemente no nos importan los métodos privados porque desde el punto de vista de las pruebas, los métodos privados no existen. Aquí hay un par de razones por las que Mockito no se burla de los métodos privados:

Requiere la piratería de cargadores de clase que nunca es a prueba de balas y cambia la API (debe usar un corrector de prueba personalizado, anotar la clase, etc.).

Es muy fácil evitarlo: simplemente cambie la visibilidad del método de privado a protegido por paquete (o protegido).

Me requiere dedicar tiempo a implementarlo y mantenerlo. Y no tiene sentido dado el punto # 2 y es un hecho que ya está implementado en una herramienta diferente (powermock).

Finalmente ... burlarse de los métodos privados es una pista de que hay algo mal con la comprensión OO. En OO desea que los objetos (o roles) colaboren, no los métodos. Olvídate de pascal y código de procedimiento. Piensa en los objetos.


No puedes hacer eso con Mockito pero puedes usar Powermock para extender Mockito y burlar los métodos privados. Powermock es compatible con Mockito. Here un ejemplo.


No se supone que debes probar métodos privados. Solo se deben probar los métodos no privados ya que estos deben llamar a los métodos privados de todos modos. Si "quieres" probar métodos privados, puede indicar que necesitas replantear tu diseño:

¿Estoy usando una inyección de dependencia adecuada? ¿Es posible que necesite mover los métodos privados a una clase separada y, en cambio, probar eso? ¿Deben estos métodos ser privados? ... ¿no pueden ser predeterminados o protegidos?

En la instancia anterior, los dos métodos que se llaman "aleatoriamente" pueden necesitar colocarse en una clase propia, probarse y luego inyectarse en la clase anterior.


Piense en esto en términos de comportamiento, no en términos de qué métodos hay. El método llamado method tiene un comportamiento particular si b es verdadero. Tiene un comportamiento diferente si b es falso. Esto significa que debe escribir dos pruebas diferentes para el method ; uno para cada caso Entonces, en lugar de tener tres pruebas orientadas a method (una para method , una para method1 , una para method2 , tiene dos pruebas orientadas al comportamiento.

Relacionado con esto (sugerí esto en otro hilo SO recientemente y recibí una palabra de cuatro letras como resultado, así que no dudes en tomar esto con un grano de sal); Me parece útil elegir nombres de prueba que reflejen el comportamiento que estoy probando, en lugar del nombre del método. Por lo tanto, no llame a sus pruebas testMethod() , testMethod1() , testMethod2() etc. Me gustan los nombres como calculatedPriceIsBasePricePlusTax() o taxIsExcludedWhenExcludeIsTrue() que indican qué comportamiento estoy probando; luego, dentro de cada método de prueba, pruebe solo el comportamiento indicado. La mayoría de estos comportamientos involucrarán solo una llamada a un método público, pero pueden implicar muchas llamadas a métodos privados.

Espero que esto ayude.


Ponga su prueba en el mismo paquete, pero una carpeta de origen diferente (src / main / java vs. src / test / java) y haga que esos métodos sean privados en paquete. La capacidad de prueba de Imo es más importante que la privacidad.


Pude probar un método privado dentro usando mockito usando reflexión. Aquí está el ejemplo, intenté nombrarlo de manera que tenga sentido

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


Realmente no entiendo tu necesidad de probar el método privado. El problema principal es que su método público ha sido anulado como tipo de devolución y, por lo tanto, no puede probar su método público. Por lo tanto, te obligan a probar tu método privado. ¿Es mi suposición correcta?

Algunas posibles soluciones (AFAIK):

  1. Burlarse de sus métodos privados, pero aún así no estará "realmente" probando sus métodos.

  2. Verifique el estado del objeto utilizado en el método. MAYORMENTE los métodos hacen algún procesamiento de los valores de entrada y devuelven una salida, o cambian el estado de los objetos. También se puede usar la prueba de los objetos para el estado deseado.

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

    [Aquí puede probar el método privado, verificando el cambio de estado de classObj de nulo a no nulo.]

  3. Refactorice su código un poco (Espero que esto no sea un código heredado). Mi funda de escribir un método es que siempre se debe devolver algo (a int / a boolean). El valor devuelto PUEDE o NO PUEDE ser utilizado por la implementación, pero SERÁ SEGURO utilizado por la prueba

    código.

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