Search code examples
c#xamarinmoqmvvmcross

Correct syntax for mocking MVVMCross navigation service using Moq


I am quite new to MVVMCross and Moq and I need some help with the format of mocking the MvxNavigation Service. I have a call in my code which I want to mock.

I would have thought I could have set the return value by doing something along the lines of:

 _naviageService.Setup(n => n.Navigate<PlaceSelectViewModel, Place, Place>(It.IsAny<Place>())).Returns(returnPlace);

but this does not compile. I have tried looking in the Moq quick start and MVVMCross example but can’t seem to find what I want. Please find complete sample below as requested: Tnx

public class FooClass
{
    IMvxNavigationService _navigationService;

    public IMvxAsyncCommand SelectPlaceCommand { get; }

    public FooClass(IMvxNavigationService navigationService)
    {
        _navigationService = navigationService;
        SelectedplaceCommand = new MvxAsyncCommand(SelectPlace);
    }

    async Task SelectPlace()
    {

        var place = await _navigationService.Navigate<PlaceSelectViewModel, Place, Place>(new Place());

        // Do somehting with place
    }

}

[TestFixture]
public class FooTests : MvxIoCSupportingTest
{
    Mock<IMvxNavigationService> _navigationService;
    FooClass _foo;

    [SetUp]
    public void SetUp()
    {
        base.Setup();

        _navigationService = new Mock<IMvxNavigationService>();
        _foo = new FooClass(_navigationService.Object);
    }

    [Test]
    public async Task DoSomthing_NavigatesToPlaceSelectViewModel()
    {
        //Arrange


        var returnPlace = new Place { MapTitle = "New Place" };

        await _navigationService.Setup(n => n.Navigate<PlaceSelectViewModel, Place>(It.IsAny<Place>())).Returns(returnPlace);  // ** This is incorrect syntax and does not complile

        //Act
        await _foo.SelectPlaceCommand.ExecuteAsync();

        //Assert
        _navigationService.Verify(s => s.Navigate<PlaceSelectViewModel, Place, Place>
                                  (It.IsAny<Place>(),
                                  null,
                                   It.IsAny<CancellationToken>()));
    }

}

Solution

  • As this issue from the Moq repository explains, you can't just skip optional parameters.

    This is kind of a workaround if you are not using all parameters in your Navigate call (or more accurate, if you don't care about them):

    _naviageService.Setup(n => n.Navigate<PlaceSelectViewModel, Place, Place>(
            It.IsAny<Place>(), 
            It.IsAny<IMvxBundle>(), 
            It.IsAny<CancellationToken>())
        ).Returns(returnPlace);