2008-09-30 19 views
34

Soy nuevo en los objetos de simulación, pero entiendo que necesito que mis clases implementen interfaces para burlarse de ellos.¿Cómo burlarse con métodos estáticos?

El problema que tengo es que en mi capa de acceso a datos, quiero tener métodos estáticos, pero no puedo poner un método estático en una interfaz.

¿Cuál es la mejor manera de evitar esto? ¿Debería usar métodos de instancia (lo cual parece incorrecto) o hay otra solución?

Respuesta

22

Usaría un patrón de objeto de método. Tener una instancia estática de esto, y llamarlo en el método estático. Debería ser posible hacer una subclase para las pruebas, dependiendo de su marco de burla.

es decir, en su clase con el método estático tienen:

private static final MethodObject methodObject = new MethodObject(); 

public static void doSomething(){ 
    methodObject.doSomething(); 
} 

y su método objeto puede ser una muy simples, fácilmente probados:

public class MethodObject { 
    public void doSomething() { 
     // do your thang 
    } 
} 
+0

¿Tiene alguna buena referencia para ese patrón? No estoy seguro de cómo voy a hacer eso. – brien

+0

Err, no en realidad. No estoy seguro de si hice ese nombre, o se lo considera más un modismo que un patrón, pero no puedo ver ninguna referencia decente de Google. Seguirá mirando sin embargo. – Grundlefleck

+1

Gracias, el ejemplo me ayudó a entender lo que quería decir. – brien

23

Sí, que utiliza los métodos de instancia . Los métodos estáticos básicamente dicen: "Hay una forma de lograr esta funcionalidad: no es polimórfica". La burla se basa en el polimorfismo.

Ahora, si sus métodos estáticos lógicamente no se preocupan por la implementación que está utilizando, podrían tomar las interfaces como parámetros, o tal vez funcionar sin interactuar con el estado en absoluto, pero de lo contrario debería estar usando instancias (y probablemente inyección de dependencia para conectar todo junto).

4

Utilice métodos de instancia siempre que sea posible.

Utilice Func [T, U] estático público (referencias de funciones estáticas que pueden sustituirse por funciones simuladas) donde los métodos de instancia no son posibles.

5

Es posible que esté tratando de probar en un punto de partida demasiado profundo. No es necesario crear una prueba para probar cada método individualmente; Los métodos privados y estáticos deben probarse llamando a los métodos públicos que luego llaman a los privados y estáticos.

lo que permite decir que su código es así:

public object GetData() 
{ 
object obj1 = GetDataFromWherever(); 
object obj2 = TransformData(obj1); 
return obj2; 
} 
private static object TransformData(object obj) 
{ 
//Do whatever 
} 

No es necesario escribir un ensayo contra el método TransformData (y no se puede). En su lugar, escriba una prueba para el método GetData que prueba el trabajo realizado en TransformData.

25

encontré una blog via google con algunos grandes ejemplos de cómo hacer esto:

  1. clase Refactor ser una clase de instancia e implementar una interfaz.

    Ya ha indicado que no desea hacer esto.

  2. Uso ejemplo una clase envoltorio con los delegados de los miembros de clases estáticas

    esta manera se puede simular una interfaz estática a través de los delegados.

  3. utilizar una clase de instancia envoltorio con los miembros protegidos que requieren la clase estática

    Este es probablemente el más fácil burlarse/prescindir de refactorización, ya que sólo puede ser heredada desde y extendido.

1

Una solución sencilla es permitir cambiar la implementación de la clase estática a través de un regulador:

class ClassWithStatics { 

    private IClassWithStaticsImpl implementation = new DefaultClassWithStaticsImpl(); 

    // Should only be invoked for testing purposes 
    public static void overrideImplementation(IClassWithStaticsImpl implementation) { 
    ClassWithStatics.implementation = implementation; 
    } 

    public static Foo someMethod() { 
    return implementation.someMethod(); 
    } 

} 

lo tanto, en la configuración de las pruebas, que llaman overrideImplementation con alguna de las interfaces burlado. El beneficio es que no necesita cambiar clientes de su clase estática. La desventaja es que probablemente tengas un pequeño código duplicado, porque tendrás que repetir los métodos de la clase estática y su implementación. Pero algunas veces los métodos estáticos pueden usar una interfaz más ligera que proporciona la funcionalidad básica.

+3

Solo un pequeño punto, ¿no tendría que declararse estática la implementación si se tuviera acceso a ella de forma estática? – Grundlefleck

0

El problema que tienes es cuando utilizas un código de terceros y se llama desde uno de tus métodos. Lo que terminamos haciendo es envolviéndolo en un objeto, y llamándolo pasándolo con dep inj, y luego su prueba unitaria puede simular un método estático de un tercero, llamar al colocador con él.

Cuestiones relacionadas