Search code examples
unit-testingmauixunitnsubstitute

DotNet MAUI 7 Unit Testing of IDispatcherTimer is Failing to Compile


I am successfully using MAUI 7 in my App We have embraced Dependency Injection using Microsoft DI Additionally we are succeeding at Constructor injection with these Dependencies and subsequent unit tests. until now when we started Injecting an Interface for IDispatcherTimer. The App Works but Unit Test will not compile.

All Source is available Here:

Typically our Pattern is to do ViewModel Testing and Mock the Injected Dependencies It has been working fine Until we created a Dependent class with an identical Interface as IDispatcherTimer The Class Works in the App but Compilaton Of the Unit Test Fails With the Error We are doing ViewModel Testing and feel our Unit TestProject should not be needing DotNet MAUI:

Severity    Code    Description Project File    Line    Suppression State
Error   CS0012  The type 'IDispatcherTimer' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. MineSweeperTests    C:\Users\markwardell\source\repos\MineSweeper\MineSweeperTests\ViewModels\SweeperViewModel-Tests.cs 28  Active

The Unit Test Fails Compilation on line 28:

enter image description here

The Constructor for the ViewModel being Tested:

public SweeperViewModel(ILogger<SweeperViewModel> logger, IGameBoardViewModel gameBoard, IDispatcherTimer dispatchTimer)
      {
         _logger = logger;
         _gameBoard = gameBoard;
         _timer = dispatchTimer;   
      }

Here is the Class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MineSweeper.Models
{
   public class GameTimer : IGameTimer
   {
      IDispatcherTimer _timer;
      public GameTimer()
      {
         _timer = Application.Current.Dispatcher.CreateTimer();
      }
      public TimeSpan Interval {  get => _timer.Interval; set => _timer.Interval = value; }
      public bool IsRepeating {  get => _timer.IsRepeating; set => _timer.IsRepeating = value; }

      public bool IsRunning => _timer.IsRunning;

      public event EventHandler Tick;

      public void Start()
      {
         _timer.Start();
      }

      public void Stop()
      {
         _timer.Stop();      
      }
   }
}

The Interface (IDENTICAL but DISTINCT from IDispatcherTimer):

namespace MineSweeper.Models
{
   public interface IGameTimer
   {
      public TimeSpan Interval { get; set; }
      public bool IsRepeating { get; set; }

      public bool IsRunning { get; }

      public event EventHandler Tick;

      public void Start();

      public void Stop();
   }
}

Solution

  • I had a missing reference to IDispatcherTimer in my VM. I replaced that with IGameTimer and it is now all good. Thanks for your comment @IToolMakerSteve