You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 17:13:15