Search code examples
c#testingprismextension-methods

Prism - how to test ShowDialogAsync (Extension method being called instead of class method)


As we know, if there are method in a class and extension method with the same signature, the method in a class should be called instead of extension one.

So my problem is the next. I'm trying to mock IDialogService from Prism.Services.Dialogs. My goal is to have a mock for ShowDialogAsync method which could be tested (static/extensions methods couldn't be mocked).

The signature of ShowDialogAsync method is:

namespace Prism.Services.Dialogs
...
public static Task<IDialogResult> ShowDialogAsync(this IDialogService dialogService, 
   string name, IDialogParameters parameters = null);

So I created class MockDialogService:

namespace LoadApp.Core.Helpers
{
    public class MockDialogService : IDialogService
    {
        public void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback)
        {
            //throw new NotImplementedException();
        }

        public Task<IDialogResult> ShowDialogAsync(string name, IDialogParameters parameters = null)
        {
            Debug.WriteLine("ShowDialogAsync");
            IDialogResult res = new DialogResult();
            return Task.FromResult(res);
        }
    }

    public class DialogResult : IDialogResult
    {
        public Exception Exception { get; set; }
        public IDialogParameters Parameters { get; set; }
    }
}

and use it in the test:

_dialogService = new MockDialogService();
...
var viewModel = new ViewModel(_dialogService);

During debug session I see dialogService in the model is the instance of my class MockDialogService. But ShowDialogAsync method from my class doesn't call, it is extension method still called. What I missed? Thank you in advance.


Solution

  • After spending some time I found the workaround.

    I created my own extension method:

    public static class MyDialogServiceExtensions
    {
        public static Task<IDialogResult> ShowDialogAsync(this IDialogService dialogService, string name, IDialogParameters parameters = null)
        {
            if (dialogService is MockDialogService myService)
            {
                return myService.ShowDialogAsync(name, parameters);
            }
            return IDialogServiceExtensions.ShowDialogAsync(dialogService, name, parameters);
        }
    }
    

    and changed calls

    await dialogService.ShowDialogAsync("MyDialogPage", parameters); 
    

    to

    await MyDialogServiceExtensions.ShowDialogAsync(dialogService, "MyDialogPage", parameters);
    

    P.S. I changed the question name to help others who have the same problem to find this topic.