LueTm
LueTm

Reputation: 2380

Unit testing view models with RelayCommands

I have a problem with my view-model unit tests. I'd like to test my code like this:

[Test]
public void SelectCommand_ExecutedWithNull_Throws()
{
    // * Arrange
    var fixture = new Fixture();
    var sut = fixture.Build();

    // * Act & Assert
    Assert.Throws<ArgumentNullException>(() => sut.SelectCommand.Execute(null));
}

The action being executed by the command:

private async void Select(IInsuranceCh insurance)
{
    if (insurance == null)
        throw new ArgumentNullException("insurance");

    try
    {
        /* ... */
    }
    catch (Exception err)
    {
        _childWindowService.ShowLoadingErrorWindow(err);
    }
    finally
    {
        IsBusy = false;
    }
}

How I hook up the command:

SelectCommand = new RelayCommand<IInsuranceCh>(Select);

When I try that however, the test fails, even though the exception is thrown and not caught in my code. When i try-catch around the sut.SelectCommand.Execute(null); statement, the catch block isn't entered. This leads me to believe, that the RelayCommand (from MVVM-Light Toolkit) is swallowing up the exception. How can I prevent that?

EDIT: Some clarifications & Assert.Throws

EDIT2: Posted action and command hookup. Maybe the async plays a role?

Upvotes: 1

Views: 241

Answers (1)

HungDL
HungDL

Reputation: 513

The reason is: RelayCommand is using reflection to invoke dynamic method. Reflection will wrap action's exception as it internal exception.

When created, the TargetInvocationException is passed a reference to the exception thrown by the method invoked through reflection. The InnerException property holds the underlying exception.
https://msdn.microsoft.com/en-us/library/system.reflection.targetinvocationexception(v=vs.110).aspx

If you want to catch an exception from external library. you must disable 'Just My Code' in debugger's options. (NUnit: Why Doesn't Assert.Throws<T> Catch My ArgumentNullException?)

Upvotes: 1

Related Questions