سؤال

أقوم بتطوير تطبيق asp.net (كلاسيكي) يحاول تنفيذ نمط MVP باستخدام هذا المثال.في محاولة وحدة اختبار مقدم العرض الخاص بي واستخدام النمط التالي، يبدو الكود 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);

كيف يمكنني التحقق من أن مقدم العرض يفعل ما هو متوقع، أي.التسجيل في أحداث التهيئة والتحميل؟بينما يتم ذلك بسهولة في مثال فيل هاك باستخدام محاكاة وحيد القرن ...

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

...كيف يمكننا أن نفعل هذا باستخدام موك؟

هل كانت مفيدة؟

المحلول

ويبدو أن هذه الوظيفة هي غير متوفرة حاليا في موك، ولكن قد تظهر في النسخة المقبلة (كان لي نظرة في بيتا 4.0.812.4، ولكن لا يبدو أن هناك).

قد يكون من المفيد طرح السؤال "لماذا SomePresenter تحتاج إلى الاشتراك عرض في Load وInit الأحداث؟" يفترض أن يكون ذلك بسبب الطبقة SomePresenter تحتاج إلى الرد على تلك الأحداث. لذلك قد يكون من الأفضل استخدام الأسلوب Raise على Mock<IView> لرفع Load وInit الأحداث، ومن ثم يؤكدون أن SomePresenter فعل الشيء الصحيح في الرد عليها.

نصائح أخرى

أعلم أن الوقت قد فات بالنسبة لـ #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);
    }
}

عرض مزيف هو مصمم تم تنفيذه على النحو التالي (انتبه إلى Events: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