C# 编写没有模拟框架的单元测试

C# 编写没有模拟框架的单元测试,c#,nunit,nsubstitute,C#,Nunit,Nsubstitute,我正在用NUnit和NSubstiture做一些单元测试 我有这门课: public class Presenter { public Presenter() { } private readonly IView _view; public Presenter(IView view) { _view = view; this._view.Loaded += OnLoaded; } private v

我正在用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")));
}
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());
}
但如何做到这一点呢

多谢各位

我试着这样做:

[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")));
}
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());
}
public-class-FakePresenter:IView
{
公共事件动作加载;
公共void呈现(字符串文本)
{
}
}
[测试]
加载视图时调用ViewRender而不使用MockingFramework()时的公共无效向量
{
//FakeMockingVIew=新的演示者(视图);
FakePresenter fPresenter=新的FakePresenter();
演示者p=新演示者(fPresenter);
fPresenter.Loaded+=Raise.Event();
fPresenter.Received();
Assert.That(fPresenter,Is.EqualTo());
}

如果您不想再使用mocking框架,那么没有什么可以阻止您创建一个从
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
方法中的文本,以便可以基于该值进行断言。

使用NSubstitute时,您必须告诉模拟视图引发事件。但是,由于IView接口不允许触发事件,只允许添加一个事件监听器,所以NSubstitute会通过附加一个特殊的事件处理程序来解决问题,它实际上会触发一个事件(我不熟悉NSubstitute,但我假设会发生这种情况):

现在,您可以轻松地从测试中触发事件:

[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"));
}

创建一个从接口派生的类,并将其用于测试。就这么简单。嗨,你这是什么意思?我已经有了带有IView依赖注入的类演示者。你能举个例子吗?感谢您使用模拟框架模拟了IVew接口。如果你不再想使用mocking框架,没有什么能阻止你创建一个从IView派生的类,并在测试中使用它作为依赖项。但是你能举个例子吗?谢谢,如果你能准确地解释一下我们要测试的内容,那会很有帮助的。这后面的部分似乎与原来的问题完全不同。你为什么要做你已经做过的事情,但是“没有模仿框架”,这也没有任何意义。这似乎没有什么意义,谢谢你,但我不明白这一点:公共事件操作加载=委托{}@SavantKing我这样做是为了事件不会为空。这样,我就不必在引发事件之前进行空检查。一路上我学会了一个小把戏。现在这已成为一种习惯,因为在较新版本的c中,您可以使用
?。
#
[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"));
}