【问题标题】:Xamarin.Essentials.NotImplementedInReferenceAssemblyException thrown when Unit Testing Xamarin.Forms app单元测试 Xamarin.Forms 应用程序时引发 Xamarin.Essentials.NotImplementedInReferenceAssemblyException
【发布时间】:2021-02-01 23:22:08
【问题描述】:

我正在为我的 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

【问题讨论】:

  • 请看github.com/xamarin/Essentials/issues/520,由于多种原因,使用 Xamarin.Essentials 进行单元测试可能需要在接口方面付出更多努力,并且有使用 Xamarin.Essentials 进行单元测试的建议。跨度>

标签: c# unit-testing xamarin.forms nunit xamarin.essentials


【解决方案1】:

我检查了您的代码,它没有引发任何 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);
        }

【讨论】:

    【解决方案2】:

    问题可能与回调试图做什么有关。例如,如果您从单元测试中调用 Xamarin.Essentials 的 Connectivity 函数,它将无法工作(并且会抛出该类型的异常),因为它没有在移动平台上运行,因此没有实现该功能。

    一个解决方案,至少我为这种类型的功能做了一个,是创建一个接口。因此,要继续上面关于连接功能的示例,我们可以这样做:

    1. 制作界面

      public interface IConnectivityService {
      
         bool CanConnect()
      }
      
    2. 定义将在应用运行期间使用的实际实现和用于测试目的的实现

      public ConnectivityService : IConnectivityService {
      
         //implement the method
      
      }
      
      public ConnectivtyServiceMock : IConnectivityService {
      
         //implement the method, but this is a mock, so it can be very skinny
      
      }
      
    3. 更新您的视图/VM 以接受此接口,并在测试用例内部实例化它的模拟版本并将其传入。

    在这种情况下,我们必须从单元测试中引用特定于设备的实现,我们必须将其抽象为接口并使用该实现来代替

    【讨论】:

    • 我没有使用 Xamarin.Essentials.Connectivity。调试时,测试在以下代码上崩溃(没有任何日志)。 HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);。我在 Try/Catch 块中执行此代码,但是,它只是崩溃了,即它没有进入 catch 块
    • 连接的例子就是这样,我遇到的一个例子是通过将它包装在一个接口中并让测试类调用它的模拟变体来解决的。现在,在您的代码中,它在尝试发送消息后会死吗?我看不出您的测试项目如何没有参考 HttpClient 的内容,因为它是 System.Net 的一部分
    • 我创建了一个示例 Xamarin.Forms 项目,其中包含单元测试。该项目可在 ...drive.google.com/drive/folders/…
    • @SahilKhanna 能否将应用发布为 github url?我认为我们中的任何人都不想去谷歌驱动器下载它
    【解决方案3】:

    您需要将Xamarin.Essentials NuGet Package 添加到您的单元测试项目中。

    我强烈建议使用依赖注入 + Xamarin.Essentials.Interfaces,因为某些 Xamarin.Essentials API 未在 .NET Core 上实现,您需要创建自己的实现。

    例如,这里有一些Xamarin.Essentials APIs I implemented in .NET Core 用于单元测试我的GitTrends 应用程序:

    【讨论】:

    • 我已经添加了 Xamarin.Essentials。调试代码,我注意到测试在下面的代码中崩溃(没有任何日志)。 HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
    • 嗨@SahilKhanna!这听起来像是一个不同的问题,需要对上面提出的问题采取不同的解决方案。由于我们已经解决了最初的问题,让我们将其标记为已回答,以帮助将来发现此问题的开发人员。为了解决您现在面临的新问题,让我们在 StackOverflow 上打开一个新问题。随时在此处链接问题作为评论,我会看看!
    • 我觉得看到的问题是一样的。该代码在 Android 和 iOS 应用程序中正确执行,但是,我在单元测试中得到错误。到目前为止,我遇到了同样的错误(如问题中所述)。我只是在调试时尝试更深入一点。
    • 我创建了一个示例 Xamarin.Forms 项目,其中包含单元测试。该项目可在 ...drive.google.com/drive/folders/…
    【解决方案4】:

    虽然您已声明此时无法将主题函数设为异步,但可以将测试设为异步。

    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.Forms 项目,其中包含单元测试。该项目可在 ...drive.google.com/drive/folders/…
    猜你喜欢
    • 2017-10-16
    • 2017-08-05
    • 1970-01-01
    • 2015-08-13
    • 2022-10-14
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多