Можно ли это поиздеваться с Moq? - PullRequest
3 голосов
/ 03 августа 2009

Я работаю над макетом некоторых внешних зависимостей и у меня проблемы с одним сторонним классом, который принимает в своем конструкторе экземпляр другого стороннего класса. Надеюсь, Сообщество может дать мне какое-то руководство.

Я хочу создать фиктивный экземпляр SomeRelatedLibraryClass, который принимает в своем конструкторе фиктивный экземпляр SomeLibraryClass. Как я могу издеваться SomeRelatedLibraryClass таким образом?

Код репо ...

Вот метод Main, который я использую в своем тестовом консольном приложении.

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

Вот класс, который я использовал, чтобы обернуть один сторонний класс и позволить ему быть 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);
    }
}

Вот два примера сторонних классов, с которыми я работаю ( ВЫ НЕ МОЖЕТЕ РЕДАКТИРОВАТЬ ЭТИ ):

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

Ответы [ 2 ]

10 голосов
/ 03 августа 2009

Я бы предложил использовать шаблон Gateway . Вместо того, чтобы напрямую зависеть от SomeRelatedLibraryClass, создайте интерфейс ISomeRelatedLibraryClassGateway. Предоставьте все методы SomeRelatedLibraryClass, которые вам нужно вызывать, с методами с одинаковой сигнатурой в ISomeRelatedLibraryClassGateway.

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

Затем создайте реализацию, которая перенаправляет все вызовы в сторонний класс:

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

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

Теперь классы в вашем приложении, которые будут зависеть от SomeRelatedLibraryClass, теперь могут вместо этого зависеть от ISomeRelatedLibraryClassGateway, и этот интерфейс легко подделать. Класс SomeRelatedLibraryClassGateway на самом деле не нуждается в модульных тестах; все, что он делает, это пропускает звонки. Это требует , чтобы быть проверенным в функциональном тесте, но вы можете сделать функциональное тестирование без насмешек.

Надеюсь, это поможет.

2 голосов
/ 03 августа 2009

AFAIK, если класс, который вы пытаетесь смоделировать, не является виртуальным или интерфейсом - вы не можете высмеять его с помощью Moq. Если ваша сторонняя библиотека не реализует их классы, я думаю, вам не повезло.

...