Проведите объект через интерфейс, чтобы его смоделировать - PullRequest
0 голосов
/ 06 февраля 2019

Я нахожусь на распутье со следующей проблемой.У меня есть, скажем, следующий класс

public class Foo
{
   internal Bar bar { get; }

   internal Foo(Bar bar)
     {
         this.bar = bar;
     }
}

, и я пытаюсь провести его юнит-тестирование, используя XUnit и Moq ,Первоначальный тест, который я создал, был

[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(Bar bar)
{
   var sut = new Foo(bar);

   Assert.NotNull(sut);
}

, который был действительным модульным тестом, но, передав в качестве параметра Bar , он вывел все свои зависимости, делая его в виде concrete тип.Предложение моего коллеги состояло в том, чтобы доставить объект Bar через интерфейс Interface и Mock , но я не уверен, как это сделать.

Я думал о создании интерфейса, метода для CreateBar с его обязательными параметрами, наследования интерфейса к классу Foo , реализации метода и добавления его в модуль.тест, но я хотел получить разъяснения или одобрение, поскольку я не уверен, что это правильный путь.

Заранее спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Очевидно, все, что мне нужно было сделать, это передать интерфейс IBar в качестве параметра вместо обычного Bar класса, потому что AutoMockData позаботился обо всем.

Так что да, ответ был: Foo class

public class Foo
{
   internal IBar bar { get; }

   internal Foo(Bar bar)
     {
         this.bar = bar;
     }
}

, и тест становится

[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(IBar bar)
{
   var sut = new Foo(bar);

   Assert.NotNull(sut);
}

Спасибо всем за помощь!

0 голосов
/ 06 февраля 2019

Вы должны получить Bar из IBar, так что вы можете легко смоделировать его с помощью Mocking Framework, например, FakeItEasy, вот пример:

public interface IBar
{
    string SayHello();
}

public class Bar : IBar
{
    public string SayHello()
    {
        // A complex work to retrieve data from external resource
        return "Hello";
    }
}

public class Foo
{
    private readonly IBar _bar;

    public Foo(IBar bar)
    {
        _bar = bar;
    }

    public string Greeting()
    {
        return _bar.SayHello();
    }
}

Теперь вы можете смоделировать IBar, чтобы получить желаемый результат:

[TestFixture]
public class FooTests
{
    [Test]
    public void Bar_ShouldReturn_HiInsteadOfHello()
    {
        IBar fakeBar = A.Fake<IBar>();
        A.CallTo(() => fakeBar.SayHello()).Returns("Hi");

        Foo sut = new Foo(fakeBar);
        Assert.AreEqual(sut.Greeting(), "Hi");
    }
}

* Примечание: Вы также можете напрямую смоделировать свой метод, не извлекая его из интерфейса, сделав его виртуальным, но вместо этого лучше использовать интерфейсы:

public class Bar
{
    public virtual string SayHello()
    {
        // A complex work to retrieve data from external resource
        return "Hello";
    }
}

public class Foo
{
    private readonly Bar _bar;

    public Foo(Bar bar)
    {
        _bar = bar;
    }

    public string Greeting()
    {
        return _bar.SayHello();
    }
}

[TestFixture]
public class FooTests
{
    [Test]
    public void Bar_ShouldReturn_HiInsteadOfHello()
    {
        Bar fakeBar = A.Fake<Bar>();
        A.CallTo(() => fakeBar.SayHello()).Returns("Hi");

        Foo sut = new Foo(fakeBar);
        Assert.AreEqual(sut.Greeting(), "Hi");
    }
}
...