繁体   English   中英

NUnit并测试Xamarin PCL

[英]NUnit and testing a Xamarin PCL

我正在开发一种便携式类库和iOS的应用,其中数据访问是基于顶部保罗贝茨 ModernHttpClient齐射改装Akavache库。 这适用于PCL和iOS应用程序,但在针对PCL创建单元测试时遇到问题。

如果我使用在Visual Studio 2015中运行的Resharper测试,我的所有测试都会通过,但如果我在Xamarin Studio中运行NUnit测试,大约一半的测试会因TypeLoadExceptions而失败。 我试图确定哪个dll导致我的问题,但据我所知,一切都是应有的。

正在测试的PCL类

   internal class ApiService<TRefitService> : IApiService<TRefitService> where TRefitService : IServiceContract
    {
        private readonly Lazy<TRefitService> background;
        private readonly Lazy<TRefitService> userInitiated;
        private readonly Lazy<TRefitService> speculative;

        private ApiService(){}

        public ApiService(string baseUrl)
        {
            ParameterGuard.ThrowIfNullOrEmpty(baseUrl, nameof(baseUrl));

            Func<string, RateLimitedHttpMessageHandler, TRefitService> createClient = (address, handler) =>
            {
                HttpClient client = new HttpClient(handler) {BaseAddress = new Uri(address)};
                return RestService.For<TRefitService>(client);
            };

            background = new Lazy<TRefitService>(() => createClient(baseUrl, new RateLimitedHttpMessageHandler(new NativeMessageHandler(), Priority.Background)));
            speculative = new Lazy<TRefitService>(() => createClient(baseUrl, new RateLimitedHttpMessageHandler(new NativeMessageHandler(), Priority.Speculative)));
            userInitiated = new Lazy<TRefitService>(() => createClient(baseUrl, new RateLimitedHttpMessageHandler(new NativeMessageHandler(), Priority.UserInitiated)));
        }

        /// <summary>
        /// Use for network requests that are running in the background.
        /// </summary>
        public TRefitService Background => background.Value; 

        /// <summary>
        /// Use to fetch data into a cache when a page loads. Expect that these requests will only get so far then give up and start failing.
        /// </summary>
        public TRefitService Speculative => speculative.Value;

        /// <summary>
        /// Use for network requests that are fetching data that the user is waiting on *right now*.
        /// </summary>
        public TRefitService UserInitiated => userInitiated.Value;
    }

Xamarin Studio失败测试

        [Test()]
        public void PassingInANullBaseUrlThrowsAnException()
        {
            Assert.Throws<ArgumentNullException>(() => new ApiService<IAuthorisationApi>(null));
        }

测试结果

预期:但是:(无法在NUnit.Framework中从程序集'/Users/206474978/Desktop/test/test/test/bin/Debug/xxx.xxx.xxx.dll'中加载类型'ApiService`1'。)。 Assert.Throws(IResolveConstraint表达式,NUnit.Framework.TestDelegate代码,System.String消息,System.Object [] args)<0x377c1c8 + 0x000e6> in:0

在NUnit.Framework.Assert.That(System.Object actual,IResolveConstraint expression,System.String message,System.Object [] args)<0x377c888 + 0x000bf> in:0 at NUnit.Framework.Assert.Throws(IResolveConstraint expression,NUnit) .Framework.TestDelegate代码,System.String消息,System.Object [] args)<0x377c1c8 + 0x00137> in:0
在NUnit.Framework.Assert.Throws(System.Type expectedExceptionType,NUnit.Framework.TestDelegate code,System.String message,System.Object [] args)<0x377bfc8 + 0x0004f> in:0
在NUnit.Framework.Assert.Throws [T](NUnit.Framework.TestDelegate代码,System.String消息,System.Object [] args)<0x377bf58 + 0x00033> in:0 at NUnit.Framework.Assert.Throws [T] (NUnit.Framework.TestDelegate代码)<0x377bf08 + 0x0003b> in:0 at test.Test + ApiServiceTest.PassingInanullBaseUrlThrowsAnException()[0x00001] in /Users/206474978/Desktop/test/test/test/Test.cs:37 at(封装器托管到本机)System.Reflection.MonoMethod:System.Reflection.MonoMethod.Invoke的SystemInvoke(System.Reflection.MonoMethod,object,object [],System.Exception&)(System.Object obj,BindingFlags invokeAttr,System。 Reflection.Binder binder,System.Object [] parameters,System.Globalization.CultureInfo culture)[0x00038] in /private/tmp/source-mono-4.2.3/bockbuild-mono-4.2.0-branch/profiles/mono- MAC-xamarin /建立根/单4.2.3 / MCS /类/ corlib /的System.Reflection / MonoMethod.cs:295

现在这通常不会成为问题,因为我只使用重塑器,但我正在Jenkins之上构建我们的持续集成管道,并通过Xamarin库中的nunit包运行测试,这导致构建报告失败。

知道这里的问题是什么吗?

UPDATE

好的,按照SushiHangover的提示,我使用了最新版本的NUnit测试运行器并得到了以下输出。 似乎错误是TypeLoadException或BadImageFormatException但我不确定为什么。 我检查了两个项目的输出,两者都设置为AnyCPU。

    [Test()]
public void PassingInAValidBaseAddressGivesAValidRefitUserInitiatedObject()
{
    var api = new ApiService<IAuthorisationApi>(BaseAddress);
    Assert.IsNotNull(api.UserInitiated);
}

    [Test()]
    public async Task PassingInAValidBaseAddressReturnsAValidAccountFromTheBackgroundObject()
    {
        //Arrange
        ApiService<IAuthorisationApi> service = = new ApiService<IAuthorisationApi>(BaseAddress);;
        //Act

        AuthorisationDto account = await service.Background.GetAuthorisationToken(logonPost, "ireland");
        //Assert
        Assert.IsTrue(account != null);
    }

无效类型xxx.xxx.Core.Services.Lib.ApiService`1,例如字段xxx.xxx.Core.Tests.ApiServiceTest + c__async0:__ 0

7) Error : xxx.xxx.Core.Tests.ApiServiceTest.PassingInAValidBaseAddressGivesAValidRefitUserInitiatedObject
System.TypeLoadException : Failure has occurred while loading a type.
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x3083b38 + 0x00093> in <filename unknown>:0 

8) Error : xxx.xxx.Core.Tests.ApiServiceTest.PassingInAValidBaseAddressReturnsAValidAccountFromTheBackgroundObject
System.BadImageFormatException : Could not resolve field token 0x040001ae
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x3083b38 + 0x00093> in <filename unknown>:0 

更新2

另一个测试失败了下面的堆栈跟踪,这看起来像单声道的一些问题?

System.TypeLoadException:无法从程序集'/Users/206474978/Documents/Development/Projects/BRSMemberApp/UnitTests/BrsGolf.Members.Core.Tests/bin/Debug/Brs.Members.Core.dll加载'ApiService`1'类型”。

at(包装器托管到本机)System.Reflection.MonoMethod:System.Reflection.MonoMethod.Invoke中的InternalInvoke(System.Reflection.MonoMethod,object,object [],System.Exception&)(System.Object obj,BindingFlags invokeAttr, System.Reflection.Binder binder,System.Object [] parameters,System.Globalization.CultureInfo culture)[0x00038] in /private/tmp/source-mono-4.2.3/bockbuild-mono-4.2.0-branch/profiles/单MAC-xamarin /建立根/单4.2.3 / MCS /类/ corlib /的System.Reflection / MonoMethod.cs:295

(这与我发布的旧答案有关)

安装的Mono框架包括相对旧版本的NUnit (版本2.4.8)。 该版本中存在许多问题/错误,范围从错误的异常捕获到解决方案/项目解析问题。

我们为OS-X构建(包括Jenkins CI)所做的是通过nuget将最新的NUnit安装到我们的解决方案根目录,并使用该安装来进行构建工件的本地测试。

就像是:

cd YourSolutionRootDir
nuget install nunit.runners
mono ./NUnit.ConsoleRunner.3.2.0/tools/nunit3-console.exe MyTestProject/bin/debug/except.dll

好,

这是一个非常令人讨厌的问题。 问题既不直接与Mono或NUnit有关。 虽然旧版NUnit引起了其他问题。

感谢@SushiHangover的提示让我开始解决这个问题。

最初,我打破了单元测试,以实例化APIService类的每个依赖项,最终通过iOS,PCL和Unit测试项目标记System.Net.Http dll的问题。 看来我正在实现的其中一个库引用了这个库的v1.5.0.0,导致项目的版本不匹配,不正确的引用(.Net,PCL等)加剧了这种情况。 我通过在每个项目app.config中包含一个特定的程序集绑定来解决这个问题。

  <dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
  </dependentAssembly>

这解决了大约80次失败的单元测试,但仍然有50次失败。

进一步探讨了PCL上的Akavache缓存库版本和单元测试项目的问题,解决了另外40个单元测试。

最后,在单元测试项目中运行Telerik的JustMock库存在一个问题,在测试PCL时,部分库似乎不受支持。 我解决了这个问题,换掉JustMock for Moq并重构一些测试。 这解决了使用Xamarin Studio进行的剩余故障单元测试。

然后我在构建服务器上运行这些测试并获得80次通过测试,87次不运行。 该死的。

为了解决这个问题,我在Xamarin v2.4.8中换掉了最新下载的默认测试运行器,现在在构建服务器上传递了所有单元测试。

简而言之, 请查看您在遇到这些问题时的参考资料

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM