Asumiendo una interfaz IReader, una implementación de la interfaz IReader ReaderImplementation y una clase ReaderConsumer que consume y procesa datos del lector.
public interface IReader
{
object Read()
}
Implementación
public class ReaderImplementation
{
...
public object Read()
{
...
}
}
Consumidor:
public class ReaderConsumer()
{
public string location
// constructor
public ReaderConsumer()
{
...
}
// read some data
public object ReadData()
{
IReader reader = new ReaderImplementation(this.location)
data = reader.Read()
...
return processedData
}
}
Para probar ReaderConsumer y el procesamiento, uso una simulación de IReader. Entonces ReaderConsumer se convierte en:
public class ReaderConsumer()
{
private IReader reader = null
public string location
// constructor
public ReaderConsumer()
{
...
}
// mock constructor
public ReaderConsumer(IReader reader)
{
this.reader = reader
}
// read some data
public object ReadData()
{
try
{
if(this.reader == null)
{
this.reader = new ReaderImplementation(this.location)
}
data = reader.Read()
...
return processedData
}
finally
{
this.reader = null
}
}
}
En esta solución, la burla introduce una oración if para el código de producción, ya que solo el constructor de burla proporciona una instancia de la interfaz.
Al escribir esto, me doy cuenta de que el bloque try-finally no está relacionado, ya que está ahí para manejar al usuario que cambia la ubicación durante el tiempo de ejecución de la aplicación.
En general se siente mal, ¿cómo podría manejarse mejor?
mocking
code-smell
Kristian mo
fuente
fuente
ReaderConsumer
independienteReaderImplementation
?Respuestas:
En lugar de inicializar el lector desde su método, mueva esta línea
En el constructor sin parámetros predeterminado.
No existe tal cosa como un "constructor simulado", si su clase tiene una dependencia que requiere para funcionar, entonces el constructor debe recibir esa cosa o crearla.
fuente
Solo necesitas el constructor único:
en su código de producción:
en tu prueba:
fuente
Examine la inyección de dependencia y la inversión del control
Tanto Ewan como RubberDuck tienen excelentes respuestas. Pero quería mencionar otra área para analizar, que es la inyección de dependencia (DI) y la inversión de control (IoC). Ambos enfoques mueven el problema que está experimentando a un marco / biblioteca para que no tenga que preocuparse por ello.
Su ejemplo es simple y se elimina rápidamente, pero, inevitablemente, va a construir sobre él y terminará con toneladas de constructores o rutinas de inicialización que se parecen a:
var foo = nuevo Foo (nuevo Bar (nuevo Baz (), nuevo Quz ()), nuevo Foo2 ());
Con DI / IoC, utiliza una biblioteca que le permite deletrear las reglas para hacer coincidir las interfaces con las implementaciones y luego simplemente dice "Give me a Foo" y descubre cómo conectar todo.
Hay muchos contenedores de IoC muy amigables (como se los llama), y voy a recomendar uno para mirar, pero, por favor, explore, ya que hay muchas buenas opciones.
Una simple para empezar es:
http://www.ninject.org/
Aquí hay una lista para explorar:
http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
fuente