Использование moq для насмешки только некоторых методов - PullRequest
53 голосов
/ 22 января 2011

У меня есть следующий метод:

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

Ответы [ 3 ]

113 голосов
/ 23 января 2011

Это называется частичной имитацией, и то, как я знаю, как это сделать в moq, требует насмешки над классом, а не над интерфейсом, и затем установкой свойства "Callbase" на вашем смоделированном объекте в "true".

Для этого потребуется сделать все методы и свойства класса, который вы тестируете, виртуальным. Предполагая, что это не проблема, вы можете написать такой тест:

 var mock = new Mock<YourTestClass>();
 mock.CallBase = true;
 mock.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);
 mockedTest.Object.MyMethod();
22 голосов
/ 16 мая 2016

Расширение на Ответ Ли ,

Вам не нужно делать все методы и свойства вашего класса виртуальными, только те, которые вы хотите высмеять.

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

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);
16 голосов
/ 21 июня 2016

У меня был похожий случай.Я обнаружил, что следующий код дал мне больше гибкости, чтобы использовать как смоделированные методы, так и реальные методы из какой-то конкретной реализации интерфейса:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...