2010-10-19 14 views
8

Soy nuevo en TDD y DDD y tengo una pregunta simple con respecto a los métodos estáticos en general. La mayoría de los gurús de TDD dicen en una palabra que los métodos estáticos son malos (y que debemos olvidarnos de crear toneladas de utilidades estáticas que nosotros (um o yo) solíamos hacer antes, ya que no son verificables. Puedo ver por qué son no comprobable (se puede encontrar un gran artículo de aclaración here para quienes estén interesados, pero supongo que soy el único novato aquí :() pero me preguntaba si existe una guía clara y agradable para usar la estática desde el punto de vista TDD?Métodos estáticos: cuándo y cuándo no

Esto puede ser una pregunta muy tonta para la mayoría de ustedes, pero algunos consejos serían geniales y solo quiero saber cómo los expertos piensan en cosas estáticas. Gracias de antemano

Editar: Mientras buscaba la respuesta Encontré 2 más buenos hilos con respecto al uso de estática (sin preocupación de TDD) que Supongo que son buenas lecturas para aquellos que están interesados ​​(incluido yo).

Respuesta

11

creo que es posible que haya un poco mal entendido.

Los métodos estáticos son verificables. Tome este método como un ejemplo:

public static int Add(int x, int y) 
{ 
    return x + y; 
} 

Esto se comprueba mediante pruebas de que el valor de retorno es lo que se espera sobre la base de los argumentos pasados ​​en

Cuando los métodos estáticos se vuelven problemáticos cuando la prueba es cuando se necesita. para presentar un simulacro

Digamos que tengo un código que llama al método estático File.Delete(). Para probar mi código sin depender del sistema de archivos, me gustaría reemplazar/simular esta llamada con una versión de prueba que simplemente verifica que ha sido invocada desde el código que se está probando. Esto es fácil de hacer si tuviera una instancia de un objeto en el que se llamaba Delete(). La mayoría (¿todos?) De los marcos burlones no pueden burlar los métodos estáticos, por lo que usar un método estático en mi código me obliga a probarlo de manera diferente (por lo general, llamando al método estático real).

Para probar algo como esto, habría que introducir una interfaz:

interface IFileDeleter 
{ 
    void Delete(string file); 
} 

Mi código entonces tomar una instancia de un objeto que implementa esta interfaz (ya sea en la llamada al método o como un parámetro en el constructor) y, a continuación, llamar a su método Delete() para hacer el borrado:

void MyMethod(string file) 
{ 
    // do whatever... 
    deleter.Delete(file); 
} 

para probar esto, se puede hacer una maqueta de la interfaz IFileDeleter y simplemente verificar que su método Delete() había sido llamado. Esto elimina la necesidad de tener un sistema de archivos real como parte de la prueba.

Esto puede parecer que el código es más complejo (lo que es), pero vale la pena por sí mismo para que sea mucho más fácil de probar.

+0

+1! Typemock puede burlarse de los métodos estáticos, pero es mejor evitarlos (cuando sea necesario burlarse de ellos). – TrueWill

+0

+1 Gracias a todos por una respuesta completa. Esperaré algunas respuestas más (si las hay) antes de seleccionar una respuesta por el bien de compartir el conocimiento – MSI

+0

Lo que pregunté fue de hecho un poco tonto ahora que leí su respuesta. Sí, tienes razón. Me perdí el punto cuando hice la pregunta. Se burla cuando surgen problemas reales; no probando el método en sí mismo especialmente cuando es solo un método de utilidad. – MSI

7

En general, si el método:

  • es lento
  • es largo
  • contiene lógica compleja
  • utiliza el sistema de archivos
  • Se conecta a una base de datos
  • Llama a una web servicio

luego evite hacerlo estático. (Consulte la respuesta de @adrianbanks para una excelente discusión de las razones detrás de esto y las alternativas.)

Básicamente, solo conviértala en estática si se trata de un método corto de conveniencia en la memoria (como muchos métodos de extensión).

+0

Me gusta mucho tu respuesta. Tiene sentido, usted toma el golpe de probar la lógica de la estática como parte del SUT, por la conveniencia que le brinda la utilidad Static, si y solo si no tiene ninguno de los rasgos que usted especificó. Por lo tanto, dado un método rápido, simple, libre de efectos secundarios, estático, usted asume que es una primitiva, una extensión de su lenguaje, y simplemente lo usa en sus unidades sin aislamiento. –

8

Evitar la estática es sin duda el camino a seguir, pero cuando no puede o está trabajando con el código heredado, la siguiente opción está disponible. A raíz de adrianbanks respuesta anterior, digamos que usted tiene los siguientes códigos (disculpas, está en Java como no sé C#):

public void someMethod() { 
    //do somethings 
    File.delete(); 
    //do some more things 
} 

puede refactorizar el File.delete() en su propio método como esto:

public void someMethod() { 
    //do somethings 
    deleteFile(); 
    //do some more things 
} 

//protected allows you to override in a subclass 
protected void deleteFile() { 
    File.delete(); 
} 

y luego en preparación para la prueba de unidad de crear una clase de simulacro que se extiende a la original y talones que la funcionalidad:

//Keep all the original functionality, but stub out the file delete functionality to 
//prevent it from using the real thing and while you're at it, keep a record that the 
//method was called. 
public class MockClass extends TheRealClass { 
    boolean fileDeleteCalled = false; 

    @Override 
    protected void deleteFile() 
     //don't actually delete the file, 
     //just record that the method to do so was called 
     fileDeleteCalled = true; 
    } 

    public boolean fileDeleteCalled() { 
     return fileDeleteCalled; 
    } 
} 

y finalmente en su prueba de unidad:

//This would normally be instantiated in the @Before method 
private MockClass unitUnderTest = new MockClass(); 

@Test 
public void testFileGetsDeleted(){ 
    assertFalse(unitUnderTest.fileDeleteCalled()); 
    unitUnderTest.someMethod(); 
    assertTrue(unitUnderTest.fileDeleteCalled()); 
} 

ahora que ha ejecutado toda la funcionalidad de algunMetodo() sin tener que borrar el archivo, y usted todavía tiene la capacidad de ver si ese método se llama.

+0

+1 para la gran idea. Gracias amigo – MSI

+0

alguien le da más votaciones por favor por el buen ejemplo y aclaración – MSI

Cuestiones relacionadas