Xamarin.Forms单元测试抛出NotImplementedInReferenceAssemblyException异常
解决Xamarin.Forms单元测试中
Xamarin.Essentials.NotImplementedInReferenceAssemblyException异常 我之前也碰到过类似的问题,这个异常本质是因为单元测试环境里引用的Xamarin.Essentials是仅包含方法签名的引用程序集,没有实际运行时实现,当代码触发到这些未实现的逻辑时就会抛出错误。哪怕你用的AutoResetEvent.WaitOne()属于System.Threading,也可能因为测试项目的依赖配置或目标框架问题,间接触发了这个异常。结合你的场景,给你几个可行的解决方案:
1. 确保测试项目引用完整的Xamarin.Essentials实现包
有时候单元测试项目默认引用的是PCL版本的Xamarin.Essentials引用程序集,没有实际的运行时代码。你可以:
- 打开测试项目的NuGet包管理器,先卸载
Xamarin.Essentials,然后重新安装最新稳定版 - 检查测试项目的目标框架:如果是.NET Core/.NET 5+,确认安装的Xamarin.Essentials版本支持该框架;如果是传统.NET Framework,要匹配对应版本的包
2. 用依赖注入模拟Xamarin.Essentials依赖(如果实际代码用到了)
如果你的SomeFunction内部实际调用了Xamarin.Essentials的API(比如定位、网络状态等),那在单元测试里必须模拟这些依赖,不能直接调用原生API。举个例子:
首先抽象出依赖接口:
public interface IEssentialsService { Task<string> FetchRequiredData(); }
然后在应用中实现这个接口(调用Xamarin.Essentials):
public class EssentialsService : IEssentialsService { public async Task<string> FetchRequiredData() { // 这里实际调用Xamarin.Essentials的API return await Task.FromResult("Hello"); } }
修改SomeClass,通过构造函数注入依赖:
public class SomeClass { private readonly IEssentialsService _essentialsService; public SomeClass(IEssentialsService essentialsService) { _essentialsService = essentialsService; } public void SomeFunction(Action<string> callback) { // 异步逻辑 _essentialsService.FetchRequiredData().ContinueWith(t => callback(t.Result)); } }
最后在单元测试里用Moq模拟这个接口:
[TestFixture()] public class Test { [Test()] public void TestCase() { AutoResetEvent autoEvent = new AutoResetEvent(false); var mockService = new Mock<IEssentialsService>(); mockService.Setup(s => s.FetchRequiredData()).ReturnsAsync("Hello"); SomeClass someClass = new SomeClass(mockService.Object); someClass.SomeFunction((response) => { Assert.AreEqual(response, "Hello"); autoEvent.Set(); }); // 加上超时时间,避免测试挂起 Assert.IsTrue(autoEvent.WaitOne(TimeSpan.FromSeconds(3))); } }
3. 替换同步等待方式(小范围修改)
虽然你说不能大规模修改项目,但可以把AutoResetEvent换成TaskCompletionSource,这种方式更适合异步回调的测试,也能减少环境依赖问题:
[Test()] public void TestCase() { TaskCompletionSource<string> tcs = new TaskCompletionSource<string>(); SomeClass someClass = new SomeClass(); someClass.SomeFunction((response) => { tcs.SetResult(response); }); // NUnit支持直接等待Task完成 var result = tcs.Task.WaitAndUnwrapException(); Assert.AreEqual(result, "Hello"); }
4. 检查测试项目的运行平台
如果你的测试项目是针对Xamarin平台(iOS/Android)的单元测试,一定要在对应的模拟器或真机上运行,不能在桌面环境跑——因为Xamarin.Essentials的实现是平台特定的,桌面环境没有对应的底层支持。如果是桌面单元测试,必须用上面的模拟方案。
内容的提问来源于stack exchange,提问作者Sahil Khanna
相关产品推荐
相关产品推荐

