Определение смоделированного ответа на основе ранних вызовов метода void для того же смоделированного объекта - PullRequest
3 голосов
/ 05 марта 2020

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

public class FooHandler
{
    private FooInstance foo;

    public void ConstructInstance(string fooSpecs)
    {
        foo = SomeMethod(fooSpecs);
    }

    public string GetSomeProperty()
    {
        return foo.SomeProperty();
    }
}

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

Код, который я хочу протестировать, требует FooHandler, и он вызывает оба метода, один за другим.

Я хочу поиздеваться над моим FooHandler, чтобы проверить, является ли мой Код вызывает это правильно.

var mockedFooHandler = new Mock<FooHandler>();
mockedFooHandler.Setup(x => x.ConstructInstance(EXAMPLE_FOO_SPEC));
mockedFooHandler.Setup(x => x.GetSomeProperty()).Returns(EXPECTED_PROPERTY);

Теперь я хочу объединить эти две установки. Я хочу вернуть разные EXPECTED_PROPERTY, если первый метод был вызван с другим EXAMPLE_FOO_SPE C. Первый метод является недействительным, а второй не принимает параметров. Так что я хочу установить внутреннее состояние объекта, как это делает реальный объект. Но состояние является частным.

Создание нескольких разных mockedFooHandlers с их собственными запрограммированными ответами для инъекции в разные места невозможно

Как мне go об этом?

Ответы [ 2 ]

1 голос
/ 05 марта 2020

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

_mockedInstance.Verify(x => x.Method(expectedParameter), Times.Once);

Если метод вызван не так, как ожидалось, то при проверке будет сгенерировано исключение, что приведет к сбою теста. Это следует вызывать в конце теста, где вы обычно подтверждаете свои результаты.

https://github.com/Moq/moq4/wiki/Quickstart#verification

0 голосов
/ 05 марта 2020

Если я правильно понимаю, вы хотите, чтобы ваш макет мог возвращать значения из одного метода в соответствии с тем, что предыдущий метод получает из тестируемого класса.

Следующее делает это путем захвата параметра, переданного первому смоделированному методу, и использования этого захваченного параметра в качестве ввода для лямбда-функции в методе Returns второго смоделированного метода.

public class UnitTest1
{
    [TestMethod]
    public void Can_Capture_Parameters()
    {
        var mockedFooHandler = new Mock<IFooHandler>();

        string response = "";

        // Here we use the moq Callback function to capture the paramter
        mockedFooHandler.Setup(x => x.ConstructInstance(It.IsAny<string>()))
            .Callback<string>(r => response = r);
        mockedFooHandler.Setup(x => x.GetSomeProperty()).Returns("b");

        mockedFooHandler.Object.ConstructInstance("testing");

        Assert.AreEqual("testing", response);
    }

    [TestMethod]
    public void Can_React_To_Parameters()
    {
        var mockedFooHandler = new Mock<IFooHandler>();

        string response = "";

        var responseDictionary = new Dictionary<string, string>()
        {
            {"first", "first response"},
            {"second", "second response"},
            {"third", "third response"}
        };

        mockedFooHandler.Setup(x => x.ConstructInstance(It.IsAny<string>()))
            .Callback<string>(r => response = r);

        // And here we use that captured parameter in a lambda. In this case using a dictionary to determine the desired response
        mockedFooHandler.Setup(x => x.GetSomeProperty()).Returns(() => responseDictionary[response]);

        mockedFooHandler.Object.ConstructInstance("first");

        Assert.AreEqual("first response", mockedFooHandler.Object.GetSomeProperty());
    }
    }

    public interface IFooHandler
    {
        void ConstructInstance(string fooSpecs);
        string GetSomeProperty();
    }

    public class FooHandler : IFooHandler
    {
        public void ConstructInstance(string fooSpecs)
        {
        }

        public string GetSomeProperty()
        {
            return "unexpected data";
        }
    }

Я, однако, согласен с комментарием Кирана Девлина, что необходимость сделать это почти наверняка является запахом кода и указывает на что-то не так с вашим дизайном.

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