1

I have two ViewModels, MainWindowShellViewModel(shellVm) and MainWindowContentViewModel(contentVm). The shellVm publishes an event and the contentVm subscribes to it.

The shell VM looks something like the following. I have omitted many details.

// ctor
public MainWindowShellViewModel(IEventAggregator eventAggregator)
{
    _EventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(IEventAggregator) + " service injected is null!!!");

    _AppStartingClosingEventToken = _EventAggregator.GetEvent<AppStartingClosingEvent>();
}

private void MainWindowShellLoaded()
{
    var payload = new AppStartingClosingEventData();
    payload.Data = "MainWindowStarting";
    _AppStartingClosingEventToken.Publish(payload);
}

The AppStartingClosingEvent is a no brainer type as follows.

public class AppStartingClosingEvent : PubSubEvent<AppStartingClosingEventData>
{ }

public class AppStartingClosingEventData
{
    public string Data { get; set; }
}

And finally, the contentVm looks as follows.

public MainWindowContentViewModel(IEventAggregator eventAggregator)
{
    _AppClosingEventToken.Subscribe(AppStartingClosing);
}
private void AppStartingClosing(AppStartingClosingEventData appStartingClosingEventData)
{
    if (appStartingClosingEventData.Data == "MainWindowStarting")
        LoadState(appStartingClosingEventData);
    if (appStartingClosingEventData.Data == "MainWindowClosing")
        SaveState(appStartingClosingEventData);
}

I want to test the that the method AppStartingClosing inside of contentVm is called with proper data. I am using Moq I am running out of ideas. Please suggest. Tried the following but so far no success.

How do I test Prism event aggregator subscriptions, on the UIThread?

Using Moq to verify a Prism event subscription fails

Unit testing with Moq, Prism 6, and Event Aggregation

Moq Event Aggregator Is it possible // Verifying a delegate was called with Moq

EDIT

Here is what I have tried.

// Arrange
var mockingKernel = new MoqMockingKernel();
var eventAggregatorMock = mockingKernel.GetMock<IEventAggregator>();
var eventBeingListenedTo = new AppStartingClosingEvent();
eventAggregatorMock.Setup(e => e.GetEvent<AppStartingClosingEvent>()).Returns(eventBeingListenedTo);            
var vm = mockingKernel.Get<MainWindowContentViewModel>();
var evData = new AppStartingClosingEventData();
evData.Data = "MainWindowStarting";

        // Act
eventBeingListenedTo.Publish(evData);

Now, what should I do? I am not even clear if I have approached correctly.

Ivan Kaloyanov
  • 1,748
  • 6
  • 18
  • 24
VivekDev
  • 20,868
  • 27
  • 132
  • 202
  • 1
    Can you show your test code? What exactly is going wrong? And, btw, show how you subscribe to the event, please. – Haukinger Jan 04 '19 at 14:04
  • 1
    On a side note: there's no need to test the event aggregator itself, that's done by the prism team already. What you can test is either whether the content vm subscribes to the correct event, or better, whether it reacts correctly to the event - but testing whether a specific method is called is neither possible nor sensible. – Haukinger Jan 04 '19 at 14:10
  • Added the test that I tried. Please check. – VivekDev Jan 04 '19 at 14:11

1 Answers1

1

Now what should I do?

After eventBeingListenedTo.Publish(evData); look whether whatever effect SaveState should have is actually happening.

I am not even clear if I have approached correctly.

You do not want to test whether one method in a class is called by another method of that class.

So instead of trying to do

subjectUnderTest.DoStuff();

MagicallyVerifyThatThisGotCalled( () => subjectUnderTest.SomeEffect() );

you should do

var subjectUnderTest = new SubjectUnderTest( serviceMock.Object );

subjectUnderTest.DoStuff();

serviceMock.Verify( x => x.SomeEffectOnTheService(), Times.Once );
Assert.That( subjectUnderTest.SomePropertyThatsChanged, Is.EqualTo( newValue ) );

Whatever SubjectUnderTest does internally to achieve the desired effect, is not in the scope of the test. It's private to SubjectUnderTest, you don't care how it is done as long as it is done at all. When testing, look at the externally visible state of your subject under test, and what it does to its dependencies.

Haukinger
  • 10,420
  • 2
  • 15
  • 28