2011-09-16 10 views
8

Por ejemplo, tengo una clase Java como la siguiente. Voy a escribir una prueba unitaria para doWork(), así que me gustaría controlar el comportamiento de obj. Pero es obvio que obj se ejemplifica internamente.¿Cómo escribir un UT para simular un objeto interno en un método?

¿Cómo puedo escribir este UT? Ahora estoy usando Junit + Mockito.

class ToBeTest{ 
    public ToBeTest(){} 
    public boolean doWork(){ 
     OtherObject obj=new OtherObject(); 
     return obj.work(); 
    } 
} 

Gracias de antemano. :)

BTW, La realidad es que estoy escribiendo UT para la clase de otra persona. Entonces no quiero cambiarlo Ha sido completamente probado por la prueba de integración.

+2

Does 'obj' * have * se crea una instancia internamente? ¿Tiene sentido tratarlo como una dependencia en su lugar? –

+0

Tienes razón. Pero la realidad es que estoy escribiendo UT para la clase de otra persona. Entonces no quiero cambiarlo Ha sido probado completamente. – Smartmarkey

+1

Y otro punto. No podemos inyectar todos los objetos en nuestra clase. Al igual que abrimos un archivo, entonces necesitamos crear una instancia de una clase de archivo. – Smartmarkey

Respuesta

7

Si no puede cambiar el código, puede utilizar Powermock junto con JUnit y Mockito burlarse de la construcción de nuevos objetos.

@Test 
public void testDoWork() throws Exception{ 

    MyTest mytest = new MyTest(); 

    OtherObj obj = new OtherObj(); 
    obj.test="mocked Test"; //here you can add any other needed values to obj 

    PowerMockito.whenNew(OtherObj.class).withNoArguments().thenReturn(obj); 

    String result = mytest.doWork(); 
    Assert.assertTrue(result.equalsIgnoreCase("mocked Test")); 
} 
+0

Muchas gracias. Eso es lo que necesito exactamente. Lo intenté Eso es genial. – Smartmarkey

1

No se puede fácilmente. Puedo pensar en dos formas en que puede hacer esto y ni Mockito ni jUnit lo soportan de manera predeterminada:

1) Manipulación del código de bytes usando cglib o una biblioteca similar que sería moderadamente difícil de hacer y probablemente bastante frágil.

2) Alternate classloader. Puede crear un cargador de clases que busque un intento de cargar la clase OtherObject y la reemplace con una clase anónima OtherObject que le proporcione el comportamiento de burla que está buscando.

Sin embargo, la mayoría de las veces se debe tratar como una dependencia. Si quieres probar la apertura de un archivo, probablemente quieras probarlo con un archivo, así que usar la clase concreta probablemente sea correcto. Si desea probar el comportamiento de un método que tiene la apertura de un archivo como parte de su lógica, puede moverlo fácilmente a una dependencia y luego simularlo. De hecho, eso generalmente tiene sentido porque lo que almacena en un archivo un día, puede necesitar almacenarse en una base de datos o ser retirado de la nube en un tercer día, por lo que segrega la lógica de lo que hace con el archivo de el proceso real de abrir una recuperación de los contenidos a menudo es una separación lógica de las preocupaciones de todos modos.

2

La mejor manera es escribir código para apoyar la prueba (Test-Driven Development es enfatizar esto). Por el momento, su código está escrito de la manera que lo hace difícil de probar.

favor considerar el uso de la inyección de dependencias, porque le ayuda a burlarse del objeto dependiente.

1

Este es un ejemplo clásico en el que debe usar dependency injection.

En resumen, en lugar de crear el objeto (dependencia) internamente, lo pasa en el constructor o utiliza una fábrica para crear lo que desea (la fábrica devuelve la implementación real en código de producción y otra en prueba). Esto le da la posibilidad de cambiar la implementación cuando realiza la prueba.

mirada a los siguientes ejemplos similares que he proporcionado o Google para "dependencia de Java ejemplo la inyección".

0

Has escrito tu código, y ahora quieres probarlo por separado. Esta es la causa fundamental de tu dificultad. Sugiero un enfoque diferente.

  1. expreso lo que el método doWork() está destinado a hacer en términos de comportamiento que pueden ser observados solamente través public y protected (getter) métodos de la clase ToBeTest, o la public y protected métodos de cualquiera associated- objectys con ToBeTest objetos. Eche un vistazo al Javadoc provisto con la biblioteca Java: que describe lo que hacen todas esas clases sin indicando los cuerpos de los métodos. ¿Cuándo el método devuelve true? ¿Cuándo devuelve false? ¿Qué efectos secundarios tiene? Es posible que deba agregar algunos métodos getter para hacer esto. Puede express these in the Javadoc for your own code.
  2. Use el comportamiento requerido para decidir qué tipos de afirmaciones puede colocar en sus pruebas unitarias.
1

Es muy fácil:

import org.junit.*; 
import mockit.*; 

@Test 
public void justMockIt() 
{ 
    new NonStrictExpectations() { OtherObject o; { o.work(); result = true; }}; 

    assert new ToBeTest().doWork(); 
} 

... cuando se utiliza JMockit.

Cuestiones relacionadas