Написание юнит-теста без насмешливой основы - PullRequest
0 голосов
/ 30 августа 2018

Я делаю некоторые юнит-тесты с NUnit и NSubstiture.

У меня есть этот класс:

public class Presenter
{
    public Presenter()
    {
    }

    private readonly IView _view;
    public Presenter(IView view)
    {
        _view = view;
        this._view.Loaded += OnLoaded;
    }
    private void OnLoaded()
    {
        _view.Render("Hello Word");
    }
}

И у меня есть этот интерфейс:

public interface IView
{
    event Action Loaded;
    void Render(string text);
}

И у меня уже есть модульное тестирование с платформой NSubstiture, например:

[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithMockingFramework()
{
    var mockView = Substitute.For<IView>();
    Presenter p = new Presenter(mockView);
    mockView.Loaded += Raise.Event<Action>();
    mockView.Received().Render(Arg.Is<string>(s => s.Contains("Hello World")));
}

Но теперь я хочу просто для целей тестирования написать тот же модульный тест, но без рамки NSubstiture:

[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
    IView view;
    Presenter MockingVIew = new Presenter(view);
}

Но как это сделать?

Спасибо

Я пытаюсь это так:

public class FakePresenter : IView
{
    public event Action Loaded;

    public void Render(string text)
    {
    }
}

[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
    //FakeMockingVIew = new Presenter(view);
    FakePresenter fPresenter = new FakePresenter();
    Presenter p = new Presenter(fPresenter);
    fPresenter.Loaded += Raise.Event<Action>();
    fPresenter.Received();
    Assert.That(fPresenter, Is.EqualTo());
}

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Когда вы использовали NSubstitute, вы должны были указать фиктивное представление, чтобы вызвать событие. Но поскольку интерфейс IView не позволяет вам инициировать событие, только добавить прослушиватель событий, NSubstitute делает обходной путь, подключая специальный обработчик событий, на самом деле запускает событие (я не знаком с NSubstitute, но я предполагаю, что это то, что происходит):

// Code here says "attact an event handler", but NSubstitute recognizes this 
// special event handler and raises the event to the "real" hanlders instead
mockView.Loaded += Raise.Event<Action>();

Таким образом, когда вы уходите от NSubstitute, вам нужно вызвать событие «правильным» способом из класса поддельного представления:

public class FakeView : IView
{
    private string RenderedText { get; private set; }
    public event Action Loaded;

    public void Render(string text)
    {
        renderedText = text;
    }

    public void RaiseLoaded() {
        if (Loaded != null) Loaded();
    }
}

Теперь вы можете легко запускать события из своего теста:

[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
    FakeView view = new FakeView();
    Presenter p = new Presenter(fPresenter);
    view.RaiseLoaded();
    Assert.That(view.RenderedText, Is.EqualTo("Hello World"));
}
0 голосов
/ 30 августа 2018

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

public class MyTestClass {

    public class FakePresenter : IView {
        public event Action Loaded = delegate { };

        public void Render(string text) {
            RenderedText = text;
        }

        public string RenderedText { get; private set; }

        public void Load() {
            Loaded();
        }
    }

    [Test]
    public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework() {
        //Arrange
        var fake = new FakePresenter();
        var subject = new Presenter(fake);
        var expected = "Hello Word";

        //Act
        fake.Load();
        var actual = fake.RenderedText;

        //Assert
        Assert.AreEqual(expected, actual);
    }
}

Приведенная выше реализация зависимости предоставляет метод Load() для вызова события для всех подписчиков, а также свойство RenderedText для захвата текста, переданного в метод Render, чтобы сделать утверждение на основе значение.

...