2010-01-30 23 views
17

Tengo un singleton independiente que supera con éxito la prueba. Pero con un grupo de pruebas, esto falla, ya que una vez que se define un singleton, no permite restablecer la instancia.Diferentes instancias Singleton con pruebas JUnit

¿Alguna idea sobre cómo hacerlo?

Respuesta

9

No utilice un singleton.

Específicamente, la única diferencia entre un singleton y una variable global es que el singleton intenta imponer una sola instancia (haciendo el constructor privado, por ejemplo).

En su lugar, haga que el constructor sea público y escriba pruebas utilizando instancias nuevas. En su programa actual, use getInstance() para obtener la instancia global canónica (o use un contenedor IOC).

Y recuerde que singletons are pathological liars.

Si todavía está demasiado cómodo con la idea de un Singleton, en lugar de hacer que el constructor sea público, puede agregar un método de fábrica público (y estático) para crear instancias que no puedan utilizarse por accidente. por ejemplo:

public static MyClass TEST_CreateInstance() { 
    return new MyClass(); 
} 
3

Puede agregar un método para destruir el singleton, por ejemplo destroyMe(); donde se desinicializa todo y se establece la instancia del singleton en nulo.

public void destroyMe(){ 
    this.instance = null; 
    //-- other stuff to turn it off. 
} 

dejaré problemas de sincronización aunque;)

Pero ¿por qué necesita para volver a inicializar su producto único para cada prueba? No debe diferir según el concepto de singleton.

10

Supongo que tiene un campo estático privado dentro de su clase singleton para almacenar la instancia inicializada.

Si no desea modificar su código, puede definir un método de desmontaje que se ejecuta después de cada prueba, y en este método establece este campo estático en nulo a través de la reflexión como se ve here.

+1

-1, IMO esto está empeorando la situación – orip

+13

+1 para dar una solución real. No tengo control sobre el código de terceros, que es un singleton, y necesito soluciones, no se me aconseja cómo hacerlo. – eis

1

en general, tenga cuidado con los singletons, con mayor frecuencia son malvados, mal diseño y tienden a representar grandes variables globales asquerosas (lo cual es malo para el mantenimiento).

de fotografías para conseguir pruebas en el lugar primero que puede hacer:

 

static setInstance(...){ //package visibility or in difficult cases you have to use public 
    instance = ...; 
} 
 

como dijo que esto es más una solución. así que obtenga el primer lugar de las pruebas, pero luego refactoría lejos del patrón de singleton.

0

La instancia de Singleton debe pasarse al SUT mediante la prueba en sí, de esa manera se crea singleton (y se destruye) para cada prueba. La adopción de la IoC y el marco de burla, como Mockito, haría que este enfoque sea casi trivial.

1

I recomiendo alejándose de Singleton como un patrón de diseño, y el uso de Singleton como un ámbito de aplicación (inyección de dependencias). Esto simplemente haría que tu problema desapareciera.

Pero asumiendo que está atrapado en el mundo de Singletons, entonces tiene algunas opciones dependiendo de si está probando el Singleton o la dependencia.

Si está probando el elemento dependiente, puede simular el Singleton utilizando PowerMock y JMockIt. Ver mi previous post sobre burlarse de Runtime.getRuntime para obtener instrucciones sobre cómo hacerlo.

Si está probando el Singleton, entonces necesita relajar las reglas de construcción o dar al Singleton un método de "Restablecer".

1

Spring proporciona la anotación DirtiesContext para este caso de uso particular donde necesita nuevas instancias de los beans singleton para cada caso de prueba. Básicamente, crea un nuevo contexto de aplicación para cada testcase/testclass que tiene esta anotación aplicada.

Cuestiones relacionadas