mardi 20 octobre 2020

How do i test the that the event aggregator published a message correctly?

These are my EventAggregator class and interfaces

public interface IEventAggregator
{
    void Publish<T>(T message) where T : IApplicationEvent;
    void Subscribe<T>(Action<T> action) where T : IApplicationEvent;
    void Unsubscribe<T>(Action<T> action) where T : IApplicationEvent;
}

public interface IApplicationEvent
{
}

class EventAggregator : IEventAggregator
{
    private static readonly IEventAggregator instance = new EventAggregator();
    public static IEventAggregator Instance { get { return instance; } }

    private readonly ConcurrentDictionary<Type, List<object>> subscriptions = new ConcurrentDictionary<Type, List<object>>();

    public void Publish<T>(T message) where T : IApplicationEvent
    {
        List<object> subscribers;
        if (subscriptions.TryGetValue(typeof(T), out subscribers))
        {
            // To Array creates a copy in case someone unsubscribes in their own handler
            foreach (var subscriber in subscribers.ToArray())
            {
                ((Action<T>)subscriber)(message);
            }
        }
    }

    public void Subscribe<T>(Action<T> action) where T : IApplicationEvent
    {
        var subscribers = subscriptions.GetOrAdd(typeof(T), t => new List<object>());
        lock (subscribers)
        {
            subscribers.Add(action);
        }
    }

    public void Unsubscribe<T>(Action<T> action) where T : IApplicationEvent
    {
        List<object> subscribers;
        if (subscriptions.TryGetValue(typeof(T), out subscribers))
        {
            lock (subscribers)
            {
                subscribers.Remove(action);
            }
        }
    }

    public void Dispose()
    {
        subscriptions.Clear();
    }
}

This is the message that i am trying to send:

public class ConfirmAddNewAffiliateMessage : IApplicationEvent
{
    public ConfirmAddNewAffiliateMessage(AdaugareAfiliatFormPresenter adaugareAfiliatFormPresenter)
    {
        AdaugareAfiliatFormPresenter = adaugareAfiliatFormPresenter;
    }
    public AdaugareAfiliatFormPresenter AdaugareAfiliatFormPresenter { get; private set; }
}

This is the method that i am trying to test

private async void OnConfirmButtonClick(object sender, EventArgs e)
    {
        var isDataLoaded = false;
        do
        {
            try
            {
                var codAfiliat = _adaugareAfiliatForm.GetCodAfiliat();
                var dataIncepereColaborare = _adaugareAfiliatForm.GetDataIncepereColaborare();
                var dataIncetareColaborare = _adaugareAfiliatForm.GetDataIncetareColaborare();
                bool addAfiliatDecision = _dialogService.PromptUser(
                   "Sunteti sigur ca doriti sa adaugati acest afiliat?",
                   "Confirmare Adaugare Afiliat");

                if (addAfiliatDecision)
                {
                   await _afiliatListQueryService.AddToListaNouaAfiliati(codAfiliat, dataIncepereColaborare, dataIncetareColaborare);
                   EventAggregator.Instance.Publish(new ConfirmAddNewAffiliateMessage(this));
                    isDataLoaded = true;
                    _adaugareAfiliatForm.CloseForm();
                }
                else
                {
                    _dialogService.Show("Ati anulat adaugarea datelor.");
                }
            }
            catch (Exception ex)
            {
                var shouldReload =
                    _dialogService.PromptUser($"{ex.Message}\nDoriti sa reincercati sa trimiteti datele", "Eroare!");
                if (!shouldReload)
                {
                    break;
                }
            }
        } while (!isDataLoaded);
    }

And finally this is my test method

[Fact]
    public void AdaugareAfiliatPublishEventTest()
    {
        //Arrange
        Mock<IAfiliatListQueryService> mockAfiliatListQueryService = new Mock<IAfiliatListQueryService>();
        Mock<IDialogService> mockDialogService = new Mock<IDialogService>();
        Mock<IAdaugareAfiliatForm> mockAdaugareAfiliatForm = new Mock<IAdaugareAfiliatForm>();
        Mock<IEventAggregator> mockEventAggregator = new Mock<IEventAggregator>();

        mockDialogService.Setup(f => f.PromptUser(It.IsAny<string>(), It.IsAny<string>())).Returns(true);
        mockEventAggregator.Setup(f =>
            f.Publish<ConfirmAddNewAffiliateMessage>(It.IsAny<ConfirmAddNewAffiliateMessage>()));

        //SUT
        AdaugareAfiliatFormPresenter sut = new AdaugareAfiliatFormPresenter(mockAdaugareAfiliatForm.Object,
            mockDialogService.Object, mockAfiliatListQueryService.Object);

        //Act
        mockAdaugareAfiliatForm.Raise(m => m.OnConfirmButtonClick += null, EventArgs.Empty);

        //Assert
        mockEventAggregator.Verify(p => p.Publish(It.IsAny<ConfirmAddNewAffiliateMessage>()));
    }

My problem is that my test always returns:

Moq.MockException : Expected invocation on the mock at least once, but was never performed: p => p.Publish(It.IsAny())

I know that the program works, but i want to write a test and can't wrap my head around this thing..

Aucun commentaire:

Enregistrer un commentaire