Как использовать moq для тестирования кода, который вызывает защищенные помощники - PullRequest
11 голосов
/ 21 октября 2011

В настоящее время я запускаю тесты, которые выглядят следующим образом:

// In Blah.cs
public class ClassUnderTest

{

    public bool MethodUnderTest()

    {

        // Do a bunch of stuff...

        return HelperMethod();

    }



    protected virtual bool HelperMethod()

    {

        bool success = false;

        // Proprietary Hardware Access.

        // Database Calls.

        // File System Modifications.

        return success;

    }

}


// In TestBlah.cs

public class TestStub : ClassUnderTest

{

    public bool HelperMethodReturnValue;



    protected override bool HelperMethod()

    {

        return HelperMethodReturnValue;

    }

}



[TestClass]

public class TestingClass

{

    [TestMethod]

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsTrue()

    {

        var stub = new TestStub();

        stub.HelperMethodReturnValue = true;

        Assert.IsTrue(stub.MethodUnderTest());

    }



    [TestMethod]

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse()

    {

        var stub = new TestStub();

        stub.HelperMethodReturnValue = false;

        Assert.IsFalse(stub.MethodUnderTest());

    }

}

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

[TestMethod]

public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse()

{

    var mockClass = new Mock<ClassUnderTest>();
    mockClass.Protected().Setup("HelperMethod").Returns(false);

    Assert.IsFalse(mockClass.Object.MethodUnderTest());

}

Кто-нибудь знает, как мне поступить?Могу ли я сделать это с moq? ​​

Ответы [ 2 ]

25 голосов
/ 21 октября 2011

Глядя на исходный код moq Я бы предположил , что вам нужно явно вызвать универсальную версию программы установки.Неуниверсальная версия, кажется, используется для пустых методов.Поэтому попробуйте

mockClass.Protected().Setup<bool>("HelperMethod").Returns(false);

Кроме этого, я бы рекомендовал переосмыслить дизайн вашего класса.Если HelperMethod () делает такую ​​кучу вещей, это будет стоить своего собственного класса, который внедряется как зависимость в ClassUnderTest.Тестирование фиктивного объекта вместо использования фиктивного объекта для проверки чего-то «реального» - это не то, для чего созданы фиктивные фреймворки (по крайней мере, не в первую очередь).

4 голосов
/ 21 октября 2011

Защищенные методы не являются отличным способом изоляции зависимостей, но иногда они появляются, особенно при адаптации устаревшего кода для тестирования.Один из вариантов, позволяющий избежать неудобного синтаксиса Moq на основе строк, - сделать метод «внутренним» защищенным (или просто «внутренним», если вы не собираетесь переопределять его при обычном использовании из других сборок.) Затем вы используете InternalsVisibleTo в сборкеразоблачить метод.Это что-то вроде взлома, но использование защищенного метода для этой цели уже является взломом.В некотором смысле я предпочитаю «внутренний» подход, поскольку он дает понять, что это метод бэкдора, который вы не должны использовать (кроме тестирования), в отличие от защищенного метода, который вы можете ожидать переопределить в обычном режиме.использование.

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