我正在开发一个试图实现MVP模式的asp.net(经典)应用程序使用此示例。在尝试对我的演示者进行单元测试并使用以下模式时,psuedocode看起来像这样

//base view interface
public interface IView
{
    event EventHandler Init;

    event EventHandler Load;

    bool IsPostBack { get; }

    void DataBind();

    bool IsValid { get;}
}

//presenter psuedo code
public class SomePresenter
{
     public SomePresenter(ISomeDomainService service, IView someView)
     {
           ...
           //HOW DO WE TEST/VERIFY THAT THIS REGISTRATION OCCURS?
           someView.Init += OnInit;
           someView.Load += OnLoad;
     }
}
...
//consuming code that exercises the above code, that needs to be tested
var presenter = new SomePresenter(someDomainService, someView);

如何验证演示者是否正在执行预期的操作,即注册Init和Load事件?虽然可以使用Rhino在 Phil Haack的示例中轻松完成此操作嘲笑...

[Test]
public void VerifyAttachesToViewEvents()
{
    viewMock.Load += null;
    LastCall.IgnoreArguments();
    viewMock.PostSaved += null;
    LastCall.IgnoreArguments();
    mocks.ReplayAll();
    new PostEditController(viewMock, 
      this.dataServiceMock);
    mocks.VerifyAll();
}

......我们怎么能用MOQ做到这一点?

有帮助吗?

解决方案

此功能似乎是目前无法使用在moq中,但可能会出现在未来的版本中(我看过4.0.812.4测试版,但它似乎并不存在)。

可能值得问这个问题,<!>“为什么SomePresenter需要订阅View的LoadInit事件?<!>”;可能是因为Raise类需要响应这些事件。因此,最好在Mock<IView>上使用<=>方法来提升<=>和<=>事件,然后断言<=>做出正确的事情来回应它们。

其他提示

我知道#Dilip可能为时已晚,但这个答案对那些试图做同样事情的人有帮助。 这是测试类

public delegate void SubscriptionHandler<T>(string name, T handler);

public class SomePresenterTest
{
    [Test]
    public void Subscription_Test()
    {
        var someServiceMock = new Mock<ISomeDomainService>();
        var viewMock = new Mock<IView>();
        //Setup your viewMock here

        var someView = new FakeView(viewMock.Object);
        EventHandler initHandler = null;            
        someView.Subscription += (n, h) => { if ((nameof(someView.Init)).Equals(n)) initHandler=h; };

        Assert.IsNull(initHandler);

        var presenter = new SomePresenter(someServiceMock.Object, someView);

        Assert.IsNotNull(initHandler);
        Assert.AreEqual("OnInit", initHandler.Method?.Name);
    }
}

FakeView 是一个实现如下的装饰器(注意事件:Init / Load {add; remove}):

public class FakeView : IView
{
    public event SubscriptionHandler<EventHandler> Subscription;
    public event SubscriptionHandler<EventHandler> Unsubscription;
    private IView _view;
    public FakeView(IView view)
    {
        Assert.IsNotNull(view);
        _view = view;
    }

    public bool IsPostBack => _view.IsPostBack;
    public bool IsValid => _view.IsValid;

    public event EventHandler Init
    {
        add
        {
            Subscription?.Invoke(nameof(Init), value);
            _view.Init += value;
        }

        remove
        {
            Unsubscription?.Invoke(nameof(Init), value);
            _view.Init -= value;
        }
    }
    public event EventHandler Load
    {

        add
        {
            Subscription?.Invoke(nameof(Load), value);
            _view.Init += value;
        }

        remove
        {
            Unsubscription?.Invoke(nameof(Load), value);
            _view.Init -= value;
        }
    }

    public void DataBind()
    {
        _view.DataBind();
    }
}

我花了一些时间来处理这个问题,我在项目中使用的解决方案是:

单元测试:

// Arrange
TestedObject.Setup(x => x.OnEvent1());
TestedObject.Setup(x => x.OnEvent2());

// Act
TestedObject.Object.SubscribeEvents();
TestedObject.Raise(x => x.Event1 += null);
TestedObject.Raise(x => x.Event2 += null);

// Assert
TestedObject.Verify(x => x.OnEvent1(), Times.Once());
TestedObject.Verify(x => x.OnEvent2(), Times.Once());

经过测试的方法:

this.Event1 += OnEvent1;
this.Event2 += OnEvent2;

因此,在调用要测试的方法之后,首先必须模拟将分配事件的方法,最后提升所有已订阅的事件。如果事件是真正订阅的,您可以检查Moq是否调用了指定的方法。

GLHF!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top