DotNet MAUI 7中IDispatcherTimer注入致单元测试编译失败
问题描述
我在MAUI 7应用中使用Microsoft依赖注入,此前构造注入和单元测试都正常。但注入IDispatcherTimer相关接口后,应用可以正常运行,单元测试却编译失败,错误提示需要引用Microsoft.Maui程序集。我认为单元测试项目不应该依赖.NET 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
相关代码
被测ViewModel构造函数
public SweeperViewModel(ILogger<SweeperViewModel> logger, IGameBoardViewModel gameBoard, IDispatcherTimer dispatchTimer) { _logger = logger; _gameBoard = gameBoard; _timer = dispatchTimer; }
GameTimer实现类
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(); } } }
IGameTimer接口(与Microsoft.Maui.Dispatching.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(); } }
解决方案
问题核心是ViewModel构造函数直接依赖了MAUI的IDispatcherTimer接口,这个类型属于Microsoft.Maui程序集,而单元测试项目没有引用该程序集,导致编译报错。你已经定义了独立的IGameTimer接口,完全可以用它来解耦ViewModel与MAUI的依赖。
具体修改步骤:
- 修改ViewModel构造函数,将参数类型从
IDispatcherTimer替换为自定义的IGameTimer:
public SweeperViewModel(ILogger<SweeperViewModel> logger, IGameBoardViewModel gameBoard, IGameTimer gameTimer) { _logger = logger; _gameBoard = gameBoard; _timer = gameTimer; }
- 在MAUI应用的DI容器中注册依赖:
builder.Services.AddSingleton<IGameTimer, GameTimer>();
- 单元测试时使用Mock实现:
用Moq等框架创建IGameTimer的Mock实例,完全不需要依赖MAUI程序集,示例如下:
var mockTimer = new Mock<IGameTimer>(); // 根据测试需求设置Mock行为,比如模拟Tick触发、验证Start/Stop调用等 var viewModel = new SweeperViewModel(mockLogger.Object, mockGameBoard.Object, mockTimer.Object);
修改后,ViewModel不再直接依赖MAUI特定类型,单元测试项目无需引用Microsoft.Maui,同时应用端的功能不受影响。
内容的提问来源于stack exchange,提问作者Mark Wardell
相关产品推荐
相关产品推荐

