Pregunta

Soy nuevo en simular objetos, pero entiendo que necesito que mis clases implementen interfaces para burlarse de ellos.

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? ¿Debo usar métodos de instancia (lo que parece incorrecto) o hay otra solución?

¿Fue útil?

Solución

Yo usaría un patrón de objeto de método. Tenga una instancia estática de esto y llámelo en el método estático. Debería ser posible crear subclases para realizar 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 objeto de método puede ser muy simple, fácil de probar:

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

Otros consejos

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

Ahora, si a sus métodos estáticos lógicamente no les importa qué implementación está usando, podrían ser capaces de tomar las interfaces como parámetros, o quizás trabajar sin interactuar con el estado, pero de lo contrario, debería estar usando instancias (y probablemente la inyección de dependencia para cablear todo junto).

Encontré un blog via google con algunos buenos ejemplos sobre cómo hacer esto:

  1. La clase de refactorización es una clase de instancia e implementa una interfaz.

    Ya has declarado que no quieres hacer esto.

  2. Use una clase de instancia de contenedor con delegados para miembros de clases estáticas

    Al hacer esto, puede simular una interfaz estática a través de delegados.

  3. Use una clase de instancia de contenedor con miembros protegidos que llaman a la clase estática

    Este es probablemente el modo más fácil de simular / administrar sin refactorizar, ya que solo puede heredarse y extenderse.

Es posible que esté intentando realizar pruebas 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 a su vez llaman a los métodos privados y estáticos.

Entonces digamos que tu 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 que escriba una prueba con el método TransformData (y no puede). En su lugar, escriba una prueba para el método GetData que prueba el trabajo realizado en TransformData.

Use métodos de instancia donde sea posible.

Use la función estática pública [T, U] (referencias de funciones estáticas que pueden sustituirse por funciones simuladas) donde los métodos de instancia no son posibles.

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

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

}

Entonces, en la configuración de tus pruebas, llamas a overrideImplementation con alguna interfaz simulada. El beneficio es que no necesita cambiar clientes de su clase estática. El inconveniente es que probablemente tendrá un poco de código duplicado, porque tendrá 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 funcionalidad básica.

El problema que tienes es cuando estás usando un código de terceros y se llama desde uno de tus métodos. Lo que terminamos haciendo es envolverlo en un objeto y llamar a pasarlo con dep inj, y luego la prueba de tu unidad puede simular un método estático de terceros.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top