1

I've read and test all these answers (this, this and this) but didn't help (also it's not my first use of mocking in such a situation, but this case is rare for me).

I'm using moq and xunit for my unit testing purpose. In testing ViewModel I mocked service and page and passed them to it, everything is working but not page.CountDialog that returns null, this is my code:

Page.cs:

public interface IPage
{
    Task<PromptResult> CountDialog(decimal previousCount);
}

PageViewModel:

public class PageViewModel : ViewModelBase<ObservableRangeCollection<Detail>>
{
    private readonly IPage _page;
    private readonly IService _service;
    private ICommand _editItemCommand;

    public PageViewModel(IService service, IPage page)
    {
        _service = service;
        _page = page;
        Data = new ObservableRangeCollection<Detail>();
    }

    public ICommand EditItemCommand
    {
        get => _editItemCommand ??
               (_editItemCommand = new Command<Detail>(async (o) => { await EditItem(o); }));
        set => _editItemCommand = value;
    }

    public async Task EditItem(Detail detail)
    {
        if (detail == null) return;
        try
        {
            var result = await _page.CountDialog(detail.Count); // It should return PromptResult (from UserDialogs lib) but every time is null, in normal running app, it works and is Not null
            if (result == null) return; //in test is usually null
            if (!result.Ok || string.IsNullOrWhiteSpace(result.Text)) return;
            var newCount = Convert.ToInt32(result.Text);
            var res = await _service.EditItem(detail, newCount);
            if (res.Status)
                UpdatePageItem(detail, newCount);
        }
        catch (RestException exception)
        {
           // nothing
        }
    }
 }

ViewModelTest.cs:

public class ViewModelTest
{
    Mock<IService> _service = new Mock<IService>();
    Mock<IPage> _page = new Mock<IPage>();
    private PageViewModel _viewModel;

    public PageViewModelTest()
    {
        _viewModel = new PageViewModel(_service.Object, _page.Object);
    }

    [Fact]
    public async Task EditItemTest_SuccessAsync()
    {
        var pageItems = GetItemsFake();
        var result = new PromptResult(true, "12"); // the result i wish to be returned (but is usually null)
        _page.Setup(x => x.CountDialog(It.IsAny<int>())).ReturnsAsync(result); // this is mock part that not work
        _service.Setup(x => x.GetItems(It.IsAny<int>())).ReturnsAsync(pageItems);// works 
        _service.Setup(c => c.EditItem(It.IsAny<int>(), It.IsAny<Detail>(), It.IsAny<int>())).ReturnsAsync(
            new ActionResponse
            {
                Result = "OK"
            });//works

        _viewModel.LoadDataCommand.Execute(true);
        await _viewModel.EditItem(pageItems .ElementAt(0)); // after this line code goes to _viewModel class and there is null
        //            _viewModel.EditItemCommand.Execute(pageItems.ElementAt(0)); // Also checked this one too, but not work too

        Assert.Equal(12, _viewModel.Data.ElementAt(0).Count); // not passed due to not working mock
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Alireza Akbari
  • 2,153
  • 2
  • 28
  • 53

1 Answers1

2

That's because CountDialog takes a decimal not an int.

Try this:

_page.Setup(x => x.CountDialog(It.IsAny<decimal>())).ReturnsAsync(result); 
Haukinger
  • 10,420
  • 2
  • 15
  • 28