Подтвердить что ты не робот

Использование 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 в отладке, я всегда перехожу к следующему утверждению.

4b9b3361

Ответ 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 чтобы увидеть, сколько раз он был вызван.