Pregunta

Estoy tratando de encontrar una manera de falsificar el resultado de un método llamado desde otro método.

Tengo un método "LoadData" que llama a un asistente independiente para obtener algunos datos y luego los transformará (estoy interesado en probar el resultado transformado).

Entonces tengo un código como este:

public class MyClass(){
  public void LoadData(){
    SomeProperty = Helper.GetSomeData();
 }
 public object SomeProperty {get;set;}
}

Quiero tener un resultado conocido del método Helper.GetSomeData().¿Puedo usar un marco simulado (tengo una experiencia bastante limitada con Rhino Mocks pero estoy abierto a cualquier cosa) para forzar un resultado esperado?¿Si es así, cómo?

*Editar: sí, como era de esperar, no pude lograr el truco que quería, tendré que encontrar una mejor manera de configurar los datos.

¿Fue útil?

Solución

Hasta donde yo sé, deberías crear una interfaz o una clase abstracta base para el objeto auxiliar.Con Rhino Mocks puedes devolver el valor que desees.

Alternativamente, puede agregar una sobrecarga para LoadData que acepte como parámetros los datos que normalmente recupera del objeto auxiliar.Esto podría ser incluso más fácil.

Otros consejos

Tienes un problema ahí.No sé si ese es un escenario simplificado de su código, pero si la clase Helper se usa de esa manera, entonces su código no se puede probar.Primero, la clase Helper se usa directamente, por lo que no puedo reemplazarlo con una burla.En segundo lugar, estás llamando a un método estático.No sé nada de C#, pero en Java no se pueden anular los métodos estáticos.

Tendrás que refactorizar un poco para poder inyectar un objeto simulado con un método ficticio GetSomeData().

En esta versión simplificada de su código es difícil darle una respuesta directa.Tienes algunas opciones:

  • Cree una interfaz para la clase Helper y proporcione una forma para que el cliente inyecte la implementación Helper en la clase MyClass.Pero si Helper es realmente una clase de utilidad, no tiene mucho sentido.
  • Cree un método protegido en MyClass llamado getSomeData y haga que solo llame a Helper.LoadSomeData.Luego reemplace la llamada a Helper.LoadSomeData en LoadData con getSomeData.Ahora puedes simular el método getSomeData para devolver el valor ficticio.

Tenga cuidado al simplemente crear una interfaz para la clase Helper e inyectarlo mediante el método.Esto puede exponer detalles de implementación.¿Por qué un cliente debería proporcionar una implementación de un utilidad clase para llamar a una operación simple?Esto aumentará la complejidad de los clientes MyClass.

Recomendaría convertir lo que tienes en algo como esto:

public class MyClass()
{
    private IHelper _helper;

    public MyClass()
    {
        //Default constructor normal code would use.
        this._helper = new Helper();
    }

    public MyClass(IHelper helper)
    {
        if(helper == null)
        {
            throw new NullException(); //I forget the exact name but you get my drift ;)
        }
        this._helper = helper;
    }

    public void LoadData()
    {
        SomeProperty = this._helper.GetSomeData();
    }
    public object SomeProperty {get;set;}
}

Ahora su clase admite lo que se conoce como inyección de dependencia.Esto le permite inyectar la implementación de la clase auxiliar y garantiza que su clase solo necesite depender de la interfaz.Cuando se burle de esto, sepa que simplemente crea un simulacro que usa la interfaz IHelper y lo pasa al constructor y su clase lo usará como si fuera la clase auxiliar real.

Ahora bien, si no puede utilizar la clase Helper como clase estática, le sugeriría que utilice un patrón de proxy/adaptador y envuelva la clase estática con otra clase que admita la interfaz IHelper (que también deberá crear).

Si en algún momento desea llevar esto un paso más allá, puede eliminar por completo la implementación predeterminada del Asistente de la clase revisada y usar contenedores IoC (Inversión de Control).Sin embargo, si esto es nuevo para usted, le recomendaría centrarse primero en los fundamentos de por qué vale la pena toda esta molestia adicional (en mi humilde opinión, lo es).

Sus pruebas unitarias se verán parecidas a este psuedocódigo:

public Amazing_Mocking_Test()
{
    //Mock object setup
    MockObject mockery = new MockObject();
    IHelper myMock = (IHelper)mockery.createMockObject<IHelper>();
    mockery.On(myMock).Expect("GetSomeData").WithNoArguments().Return(Anything);

    //The actual test
    MyClass testClass = new MyClass(myMock);
    testClass.LoadData();

    //Ensure the mock had all of it's expectations met.
    mockery.VerifyExpectations();
}

No dudes en comentar si tienes alguna pregunta.(Por cierto, no tengo idea de si este código funciona. Simplemente lo escribí en mi navegador, principalmente estoy ilustrando los conceptos).

Es posible que desees investigar Typemock Isolator, que puede "falsificar" llamadas a métodos sin obligarte a refactorizar tu código.Soy un desarrollador en esa compañía, pero la solución es viable si desea elegir no cambiar su diseño (o obligado a no cambiarlo para la capacidad de prueba) está en www.typemock.com

Blog de Roy:ISerializable.com

Sí, un marco burlón es exactamente lo que estás buscando.Puede grabar/organizar cómo desea que regresen ciertas clases simuladas o eliminadas.

Rhino Mocks, Typemock y Moq son buenas opciones para hacer esto.

La publicación de Steven Walther. El uso de Rhino Mocks me ayudó mucho cuando comencé a jugar con Rhino Mocks.

Yo intentaría algo como esto:

public class MyClass(){
  public void LoadData(IHelper helper){
    SomeProperty = helper.GetSomeData();
 }

De esta manera puedes simular la clase auxiliar usando, por ejemplo, MOQ.

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