Question Vérification de l'enregistrement des événements à l'aide de Moq


Je développe une application asp.net (classique) essayant d'implémenter le modèle MVP en utilisant cet exemple. En essayant de tester mon présentateur et en utilisant le modèle suivant, le pseudo-code pour lequel il ressemble

//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);

Comment est-ce que je vérifie que le présentateur fait ce qui est attendu c'est-à-dire, en vous inscrivant pour les événements d'initialisation et de charge? Bien que cela se fasse facilement dans le L'exemple de Phil Haack en utilisant Rhino mocks ...

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

... comment pouvons-nous faire cela en utilisant MOQ?


22
2017-09-15 20:59


origine


Réponses:


Il semblerait que cette fonctionnalité soit pas disponible actuellement dans moq, mais peut apparaître dans une future version (j'ai regardé dans la version bêta 4.0.812.4, mais cela ne semble pas être là).

Il peut être intéressant de poser la question, "pourquoi SomePresenter besoin de s'abonner à la vue Load et Init événements? "Vraisemblablement c'est parce que le SomePresenter classe doit répondre à ces événements. Donc, il serait préférable d'utiliser le Raise méthode sur votre Mock<IView> relever le Load et Init événements, puis affirmer que SomePresenter fait la bonne chose en réponse à eux.


14
2017-09-15 22:08



J'ai passé du temps avec cette question et la solution que j'utilise dans mon projet est la suivante:

Test de l'unité:

// 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());

Méthode testée:

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

Donc, vous devez d'abord vous moquer des méthodes que vous allez assigner aux événements, après avoir appelé la méthode que vous souhaitez tester, et enfin lever tous les événements souscrits. Si l'événement est vraiment souscrit, vous pouvez vérifier avec Moq si la méthode assignée est appelée.

GL HF!


0
2017-07-17 19:12



Je sais que c'est peut-être trop tard pour #Dilip, mais cette réponse peut être utile pour ceux qui essaient de faire la même chose. Voici la classe de test

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 est un décorateur implémenté comme suit (faites attention aux événements: 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();
    }
}

0
2018-01-14 03:38