Частичное высмеивание внутреннего метода класса с помощью Moq

У меня есть класс, который содержит открытый метод, который опирается на внутренний метод для правильного возврата его значения.

Давайте рассмотрим следующий класс и тестовый файл:

public class ClassUnderTest
{
    public string NotMockedPublicMethod()
    {
        return MockedMethod();
    }

    virtual public string MockedMethod()
    {
        return "original";
    }
}

Следующий контрольный пример будет работать:

var mock = new Mock<ClassUnderTest> { CallBase = true };
mock.Setup(m => m.MockedMethod()).Returns("mocked");

Assert.AreEqual("mocked", mock.Object.NotMockedPublicMethod());

Но скажем так MockedMethod() у меня нет никакой полезности внешне. Проблема в том, что маркировка этого метода как internal (даже используя InternalsVisibleTo() должным образом):

virtual internal string MockedMethod()

сделает точно такой же тест не с сообщением Assert.AreEqual failed. Expected:<mocked>. Actual:<original>,

Это ошибка Moq или какое-то ограничение?

1 ответ

Решение

Это не ошибка или ограничение. Ваш тест не пройден после создания метода внутренним (даже после добавления InternalsVisibleTo), потому что он не вызывает проверяемый метод, а вызывает фактический метод.

Вам необходимо добавить InternalsVisibleTo для DynamicProxyGenAssembly2, а также по указанному ниже URL-адресу.

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

http://www.blackwasp.co.uk/MoqInternals.aspx

URL не дает правильного объяснения, но вот оно:

Moq использует DynamicProxy Castle Project для генерации прокси на лету во время выполнения, так что члены объекта могут быть перехвачены без изменения кода класса. Вот как Moq возвращает значение, указанное в "Setup().Returns" (в вашем случае строка "mocked")

URL-адрес динамического прокси: http://www.castleproject.org/projects/dynamicproxy/

Я посмотрел исходный код (см. URL ниже) для DynamicProxy и вижу, что он использует "DynamicProxyGenAssembly2" в качестве имени сборки для сгенерированной сборки, и поэтому вам также необходимо добавить InternalsVisibleTo для DynamicProxyGenAssembly2.

public static readonly String DEFAULT_ASSEMBLY_NAME = "DynamicProxyGenAssembly2";

https://github.com/castleproject/Castle.DynamicProxy-READONLY/blob/ed8663b23a54bed641e5f97e39a6bc16fe0d976f/src/Castle.DynamicProxy/ModuleScope.cs

Другие вопросы по тегам