Pregunta

Estoy trabajando en burlarme de algunas dependencias externas y estoy teniendo problemas con una clase de terceros que toma en su constructor una instancia de otra clase de terceros. Esperemos que la comunidad SO pueda darme alguna dirección.

Quiero crear una instancia simulada de SomeRelatedLibraryClass que tome en su constructor una instancia simulada de SomeLibraryClass . ¿Cómo puedo burlarme de SomeRelatedLibraryClass de esta manera?

El código de repositorio ...

Aquí hay un método principal que estoy usando en mi aplicación de consola de prueba.

public static void Main()
{
    try
    {
        SomeLibraryClass slc = new SomeLibraryClass("direct to 3rd party");
        slc.WriteMessage("3rd party message");
        Console.WriteLine();

        MyClass mc = new MyClass("through myclass");
        mc.WriteMessage("myclass message");
        Console.WriteLine();

        Mock<MyClass> mockMc = new Mock<MyClass>("mock myclass");
        mockMc.Setup(i => i.WriteMessage(It.IsAny<string>()))
            .Callback((string message) => Console.WriteLine(string.Concat("Mock SomeLibraryClass WriteMessage: ", message)));

        mockMc.Object.WriteMessage("mock message");
        Console.WriteLine();
    }
    catch (Exception e)
    {
        string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
        Console.WriteLine(error);
    }
    finally
    {
        Console.Write("Press any key to continue...");
        Console.ReadKey();
    }
}

Aquí hay una clase que he usado para envolver una clase de terceros y permitir que sea Moq'd:

public class MyClass
{
    private SomeLibraryClass _SLC;

    public MyClass(string constructMsg)
    {
        _SLC = new SomeLibraryClass(constructMsg);
    }

    public virtual void WriteMessage(string message)
    {
        _SLC.WriteMessage(message);
    }
}

Aquí hay dos ejemplos de clases de terceros con las que estoy trabajando ( NO PUEDES EDITAR ESTAS ):

public class SomeLibraryClass
{
    public SomeLibraryClass(string constructMsg)
    {
        Console.WriteLine(string.Concat("SomeLibraryClass Constructor: ", constructMsg));
    }

    public void WriteMessage(string message)
    {
        Console.WriteLine(string.Concat("SomeLibraryClass WriteMessage: ", message));
    }
}

public class SomeRelatedLibraryClass
{
    public SomeRelatedLibraryClass(SomeLibraryClass slc)
    {
        //do nothing
    }

    public void WriteMessage(string message)
    {
        Console.WriteLine(string.Concat("SomeRelatedLibraryClass WriteMessage: ", message));
    }
}
¿Fue útil?

Solución

AFAIK, si la clase que estás tratando de burlar no es virtual o una interfaz, no puedes burlarte de ella con Moq. Si su biblioteca de terceros no implementa sus clases, creo que no tiene suerte.

Otros consejos

Sugeriría utilizar el patrón Gateway . En lugar de depender directamente de SomeRelatedLibraryClass, cree una interfaz ISomeRelatedLibraryClassGateway. Exponga todos los métodos de SomeRelatedLibraryClass que necesita llamar con métodos de la misma firma en ISomeRelatedLibraryClassGateway.

public interface ISomeRelatedLibraryClassGateway {
  void WriteMessage(string message);
}

Luego cree una implementación que enrute todas las llamadas a la clase de terceros:

public class SomeRelatedLibraryClassGateway : ISomeRelatedLibraryClassGateway {
  private readonly SomeRelatedLibraryClass srlc;
  public SomeRelatedLibraryClassGateway(SomeRelatedLibraryClass srlc) {
    this.srlc = srlc;
  }

  void ISomeRelatedLibraryClassGateway.WriteMessage(string message) {
    srlc.WriteMessage(message);
  }
}

Ahora las clases en su aplicación que dependerían de SomeRelatedLibraryClass ahora pueden depender de ISomeRelatedLibraryClassGateway, y esta interfaz es fácil de burlar. La clase SomeRelatedLibraryClassGateway realmente no necesita pruebas unitarias; todo lo que hace es pasar las llamadas. necesita probarse en una prueba funcional, pero puede hacer pruebas funcionales sin simulacros.

Espero que esto ayude.

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