Частичное высмеивание внутреннего метода класса с помощью 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";