Xamarin.Essentials.NotImplementedInReferenceAssemblyException 单元测试 Xamarin.Forms 应用程序时抛出
Xamarin.Essentials.NotImplementedInReferenceAssemblyException thrown when Unit Testing Xamarin.Forms app
我正在为我的 Xamarin.Forms 应用程序进行 运行 单元测试,单元测试抛出 Xamarin.Essentials.NotImplementedInReferenceAssemblyException
:
我已经为应用程序创建了一个单元测试项目(使用 NUnit 3.12.0)并编写了以下代码来测试功能。
[TestFixture()]
public class Test
{
[Test()]
public void TestCase()
{
AutoResetEvent autoEvent = new AutoResetEvent(true);
SomeClass someClass = new SomeClass();
someClass.SomeFunction((response) =>
{
Assert.AreEqual(response, "Hello")
autoEvent.Set();
});
autoEvent.WaitOne(); //** Xamarin.Essentials.NotImplementedInReferenceAssemblyException thrown here**
}
}
下面是来自 Xamarin.Forms 应用程序的测试代码:
public class SomeClass
{
public void SomeFunction(Action<string> callback)
{
// asynchronous code...
callback("Hello");
}
}
上述功能在 Xamarin.Forms 应用程序中运行良好。
注意:我读到可以使用await/async,但是,我将不得不在整个项目中进行更改。这暂时不是一个可行的方案。
编辑 1:
我创建了一个示例 Xamarin.Forms 项目,其中包含单元测试。该项目可用 here
虽然您已经声明主题函数此时不能异步,但是测试可以异步。
TaskCompletionSource
可用于等待回调被调用
[TestFixture()]
public class Test {
[Test()]
public async Task TestCase() {
//Arrange
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
Action<string> callback = (arg) => {
tcs.TrySetResult(arg);
};
SomeClass someClass = new SomeClass();
//Act
someClass.SomeFunction(callback);
string response = await tcs.Task;
//Assert
Assert.AreEqual(response, "Hello")
}
}
您需要将 Xamarin.Essentials NuGet Package 添加到您的单元测试项目。
我强烈建议使用依赖注入 + Xamarin.Essentials.Interfaces,因为某些 Xamarin.Essentials API 未在 .NET Core 上实现,您需要创建自己的实现。
例如,这里有一些 Xamarin.Essentials APIs I implemented in .NET Core for Unit Testing my GitTrends 应用程序:
该问题可能与回调尝试执行的操作有关。例如,如果您从单元测试中调用它,Xamarin.Essentials 的连接功能将不起作用(并且会抛出该类型的异常),因为它在移动平台上不是 运行,因此不会'没有实现该功能。
对此的一种解决方案(至少我为此类功能所做的一种解决方案)是创建一个界面。因此,要继续上面关于连接功能的示例,我们可以这样做:
制作界面
public interface IConnectivityService {
bool CanConnect()
}
定义将在应用程序中使用的实际实现 运行,以及用于测试目的的实现
public ConnectivityService : IConnectivityService {
//implement the method
}
public ConnectivtyServiceMock : IConnectivityService {
//implement the method, but this is a mock, so it can be very skinny
}
更新您的 View/VM 以接受此接口,并在测试用例内部实例化它的模拟版本并将其传入。
在我们必须从单元测试中引用设备特定实现的情况下,我们必须在接口中将其抽象出来并改用该实现
我检查了你的代码,它没有抛出任何 Xamarin.Essentials 异常。为了 运行 单元测试,我必须添加“NUnit3TestAdapter”nuget 包。
您必须等待回调,否则测试会崩溃。您可以使用@Nkosi 建议的 TaskCompletionSource。
[Test()]
public async Task TestCase()
{
XamarinMock.Init();
WebApi webApi = new WebApi();
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
Action<HttpResponseMessage> callback = (arg) => {
tcs.TrySetResult(arg);
};
webApi.Execute(callback);
var response = await tcs.Task;
Console.WriteLine(response);
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
}
我正在为我的 Xamarin.Forms 应用程序进行 运行 单元测试,单元测试抛出 Xamarin.Essentials.NotImplementedInReferenceAssemblyException
:
我已经为应用程序创建了一个单元测试项目(使用 NUnit 3.12.0)并编写了以下代码来测试功能。
[TestFixture()]
public class Test
{
[Test()]
public void TestCase()
{
AutoResetEvent autoEvent = new AutoResetEvent(true);
SomeClass someClass = new SomeClass();
someClass.SomeFunction((response) =>
{
Assert.AreEqual(response, "Hello")
autoEvent.Set();
});
autoEvent.WaitOne(); //** Xamarin.Essentials.NotImplementedInReferenceAssemblyException thrown here**
}
}
下面是来自 Xamarin.Forms 应用程序的测试代码:
public class SomeClass
{
public void SomeFunction(Action<string> callback)
{
// asynchronous code...
callback("Hello");
}
}
上述功能在 Xamarin.Forms 应用程序中运行良好。
注意:我读到可以使用await/async,但是,我将不得不在整个项目中进行更改。这暂时不是一个可行的方案。
编辑 1: 我创建了一个示例 Xamarin.Forms 项目,其中包含单元测试。该项目可用 here
虽然您已经声明主题函数此时不能异步,但是测试可以异步。
TaskCompletionSource
可用于等待回调被调用
[TestFixture()]
public class Test {
[Test()]
public async Task TestCase() {
//Arrange
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
Action<string> callback = (arg) => {
tcs.TrySetResult(arg);
};
SomeClass someClass = new SomeClass();
//Act
someClass.SomeFunction(callback);
string response = await tcs.Task;
//Assert
Assert.AreEqual(response, "Hello")
}
}
您需要将 Xamarin.Essentials NuGet Package 添加到您的单元测试项目。
我强烈建议使用依赖注入 + Xamarin.Essentials.Interfaces,因为某些 Xamarin.Essentials API 未在 .NET Core 上实现,您需要创建自己的实现。
例如,这里有一些 Xamarin.Essentials APIs I implemented in .NET Core for Unit Testing my GitTrends 应用程序:
该问题可能与回调尝试执行的操作有关。例如,如果您从单元测试中调用它,Xamarin.Essentials 的连接功能将不起作用(并且会抛出该类型的异常),因为它在移动平台上不是 运行,因此不会'没有实现该功能。
对此的一种解决方案(至少我为此类功能所做的一种解决方案)是创建一个界面。因此,要继续上面关于连接功能的示例,我们可以这样做:
制作界面
public interface IConnectivityService { bool CanConnect() }
定义将在应用程序中使用的实际实现 运行,以及用于测试目的的实现
public ConnectivityService : IConnectivityService { //implement the method } public ConnectivtyServiceMock : IConnectivityService { //implement the method, but this is a mock, so it can be very skinny }
更新您的 View/VM 以接受此接口,并在测试用例内部实例化它的模拟版本并将其传入。
在我们必须从单元测试中引用设备特定实现的情况下,我们必须在接口中将其抽象出来并改用该实现
我检查了你的代码,它没有抛出任何 Xamarin.Essentials 异常。为了 运行 单元测试,我必须添加“NUnit3TestAdapter”nuget 包。
您必须等待回调,否则测试会崩溃。您可以使用@Nkosi 建议的 TaskCompletionSource。
[Test()]
public async Task TestCase()
{
XamarinMock.Init();
WebApi webApi = new WebApi();
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
Action<HttpResponseMessage> callback = (arg) => {
tcs.TrySetResult(arg);
};
webApi.Execute(callback);
var response = await tcs.Task;
Console.WriteLine(response);
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
}