Использование moq для издевки только некоторых методов
У меня есть следующий метод:
public CustomObect MyMethod()
{
var lUser = GetCurrentUser();
if (lUser.HaveAccess)
{
//One behavior
}
else
{
//Other behavior
}
//return CustomObject
}
Я хочу высмеять IMyInterface.GetCurrentUser
, так что при вызове MyMethod
я мог бы получить один из путей кода, чтобы проверить его. Как это сделать с помощью Moq?
Я делаю следующее:
var moq = new Mock<IMyInterface>();
moq.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);
//act
var lResult = moq.Object.MyMethod();
Но по какой-то причине lResult
всегда null
, и когда я пытаюсь войти в MyMethod
в отладке, я всегда перехожу к следующему утверждению.
Ответы
Ответ 1
Это называется частичным макетом, и способ, которым я это знаю в moq, требует издеваться над классом, а не с интерфейсом, а затем устанавливать свойство "Callbase" на вашем издеваемом объекте на "true".
Это потребует создания всех методов и свойств класса, который вы тестируете виртуальным. Предполагая, что это не проблема, вы можете написать тест следующим образом:
var mock = new Mock<YourTestClass>();
mock.CallBase = true;
mock.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);
mockedTest.Object.MyMethod();
Ответ 2
Расширение на lee answer,
Вам не нужно делать все методы и свойства виртуального класса, только те, которые вы хотите высмеять.
Кроме того, следует отметить, что вы должны издеваться над конкретной реализацией своего класса.
var mock = new Mock<YourTestClass>(); // vs. var mock = new Mock<IYourTestInterface>();
Если ваш класс не имеет конструктора по умолчанию, вам также необходимо указать аргументы для его прохождения через:
var mock = new Mock<YourTestClass>(x, y, z);
// or
var mock = new Mock<YourTestClass>(MockBehavior.Default, x, y, z);
Где x, y, z
- это первый, второй и третий параметры для вашего конструктора.
И, наконец, если метод, который вы ищете для подделки, защищен, вам необходимо включить Moq.Protected
using Moq.Protected;
TReturnType returnValue = default(TReturnType);
mock.Protected()
.Setup<TReturnType>("YourMockMethodName", It.IsAny<int>()) // methodname followed by arguments
.Returns(returnValue);
Ответ 3
У меня был похожий случай. Я обнаружил, что следующий код дал мне больше гибкости, чтобы использовать как смоделированные методы, так и реальные методы из какой-то конкретной реализации интерфейса:
var mock = new Mock<ITestClass>(); // Create Mock of interface
// Create instance of ITestClass implementation you want to use
var inst = new ActualTestClass();
// Setup to call method of an actual instance
// if method returns void use mock.Setup(...).Callback(...)
mock.Setup(m => m.SomeMethod(It.IsAny<int>())
.Returns((int x) => inst.SomeMethod(x));
Теперь вы можете использовать реальный метод, но также использовать такие вещи, как Verify
чтобы увидеть, сколько раз он был вызван.