Как я могу создать и использовать частичную заглушку (в MoQ), не привязываясь к конкретному подтексту? - PullRequest
0 голосов
/ 08 октября 2010

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

Так, например, у меня есть фабричный метод, такой как:

private Mock<ISomeInterface> ISomeInterfaceStubFactory()
{
    return new Mock<SomeConcreteImplementation>();
}

Вот код, который вызывает метод:

var partialStub = ISomeInterfaceStubFactory();            
partialStub.Setup(m => m.MethodToStubOutThatMethodToTestCalls(It.IsAny<string>())).Returns(new List<SomeOtherObject>());
partialStub.CallBase = true;

var actualResult= partialStub.Object.MethodToTest();

Assert.That(actualResult, Is.EqualTo(expectedResult));

Проблема в том,при этом ISomeInterfaceStubFactory не будет компилироваться.Таким образом, я изменил это, чтобы быть как ниже, но выполнение этого, кажется, ломает частичную заглушку.Реализована фактическая реализованная операция MethodToStubOutThatMethodToTestCalls, а не версия с заглушкой.В основном я пытаюсь использовать полиморфизм с объектом-заглушкой.Есть какой-либо способ сделать это?Мне бы хотелось, чтобы мой модульный тест не был тесно связан с конкретной реализацией.

private Mock<ISomeInterface> ISomeInterfaceStubFactory()
{
    return new Mock<SomeConcreteImplementation>.As<ISomeInterface>();
}

Ответы [ 2 ]

2 голосов
/ 08 октября 2010

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

0 голосов
/ 10 октября 2010

Пересмотр моего ответа в соответствии с вашими разъяснениями.Я не согласен с arootbeer, но я хочу понять, что вы делаете и почему это не работает.

Вот простой пример того, что, я думаю, вы пытаетесь сделать.Тест проходит для меня для обеих конкретных реализаций.Это то, что вы пытаетесь сделать, и работает ли этот пример для вас?

Интерфейс и классы:

using System;

namespace ClassLibrary1
{
    public interface IFoo
    {
        string GetBaseString();
        string GetExtendedString();
    }
    public class Foo_A : IFoo
    {
        public virtual string GetBaseString()
        {
            return "Foo_A";
        }
        public virtual string GetExtendedString()
        {
            return GetBaseString() + "_Bar";
        }
    }
    public class Foo_B : IFoo
    {
        public virtual string GetBaseString()
        {
            return "Foo_B";
        }
        public virtual string GetExtendedString()
        {
            return GetBaseString() + "_Bar";
        }
    }
}

Юнит тест:

using System;
using Xunit;
using Moq;

namespace ClassLibrary1.UnitTests
{
    public class Class1
    {
        [Fact]
        public void GetExtendedString_ReturnsExtendedString()
        {
            var partialFoo = IFooFactory();

            partialFoo.Setup(x => x.GetBaseString()).Returns("Foo");
            partialFoo.CallBase = true;

            string result = partialFoo.Object.GetExtendedString();

            Assert.Equal("Foo_Bar", result);
        }

        private Mock<IFoo> IFooFactory()
        {
            return new Mock<Foo_A>().As<IFoo>();
            //return new Mock<Foo_B>().As<IFoo>();
        }
    }
}
...