简体   繁体   English

NUnit并测试Xamarin PCL

[英]NUnit and testing a Xamarin PCL

I am developing a portable class library and iOS app where the data access is based on top of Paul Betts' ModernHttpClient , Fusillade , Refit and Akavache libraries. 我正在开发一种便携式类库和iOS的应用,其中数据访问是基于顶部保罗贝茨 ModernHttpClient齐射改装Akavache库。 This works in the PCL and iOS apps but I am having an issue when creating unit tests against the PCL. 这适用于PCL和iOS应用程序,但在针对PCL创建单元测试时遇到问题。

If I use the Resharper test running within Visual Studio 2015 all my tests pass but if I run the NUnit tests in Xamarin Studio about half the tests fail with TypeLoadExceptions . 如果我使用在Visual Studio 2015中运行的Resharper测试,我的所有测试都会通过,但如果我在Xamarin Studio中运行NUnit测试,大约一半的测试会因TypeLoadExceptions而失败。 I have tried to determine which dll is causing me the problems but as far as I can see everything is as it should be. 我试图确定哪个dll导致我的问题,但据我所知,一切都是应有的。

PCL Class under test 正在测试的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 Failing Test Xamarin Studio失败测试

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

Test Result 测试结果

Expected: But was: (Could not load type 'ApiService`1' from assembly '/Users/206474978/Desktop/test/test/test/bin/Debug/xxx.xxx.xxx.dll'.) at NUnit.Framework.Assert.Throws (IResolveConstraint expression, NUnit.Framework.TestDelegate code, System.String message, System.Object[] args) <0x377c1c8 + 0x000e6> in :0 预期:但是:(无法在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

at 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 code, System.String message, System.Object[] args) <0x377c1c8 + 0x00137> 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
at 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(System.Type expectedExceptionType,NUnit.Framework.TestDelegate code,System.String message,System.Object [] args)<0x377bfc8 + 0x0004f> in:0
at NUnit.Framework.Assert.Throws[T] (NUnit.Framework.TestDelegate code, System.String message, System.Object[] args) <0x377bf58 + 0x00033> in :0 at NUnit.Framework.Assert.Throws[T] (NUnit.Framework.TestDelegate code) <0x377bf08 + 0x0003b> in :0 at test.Test+ApiServiceTest.PassingInANullBaseUrlThrowsAnException () [0x00001] in /Users/206474978/Desktop/test/test/test/Test.cs:37 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) [0x00038] in /private/tmp/source-mono-4.2.3/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.3/mcs/class/corlib/System.Reflection/MonoMethod.cs:295 在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

Now this wouldn't normally be an issue as I would just use reshaper but I am building our Continuous Integration pipeline on top of Jenkins and running the tests via the nunit package within the Xamarin libraries which results in the build reporting failures. 现在这通常不会成为问题,因为我只使用重塑器,但我正在Jenkins之上构建我们的持续集成管道,并通过Xamarin库中的nunit包运行测试,这导致构建报告失败。

Any idea what the problem is here? 知道这里的问题是什么吗?

UPDATE UPDATE

Ok, after follow the tip from SushiHangover I used the latest version of NUnit test runner and got the following output. 好的,按照SushiHangover的提示,我使用了最新版本的NUnit测试运行器并得到了以下输出。 Seems like the errors are either TypeLoadException or BadImageFormatException but i'm unsure why. 似乎错误是TypeLoadException或BadImageFormatException但我不确定为什么。 I checked the output for both projects and both are set to AnyCPU. 我检查了两个项目的输出,两者都设置为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);
    }

Invalid type xxx.xxx.Core.Services.Lib.ApiService`1 for instance field xxx.xxx.Core.Tests.ApiServiceTest+c__async0:__0 无效类型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 

UPDATE 2 更新2

Another tests fails with the below stacktrace, this looks like some issue with mono? 另一个测试失败了下面的堆栈跟踪,这看起来像单声道的一些问题?

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

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) [0x00038] in /private/tmp/source-mono-4.2.3/bockbuild-mono-4.2.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.2.3/mcs/class/corlib/System.Reflection/MonoMethod.cs:295 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

(This is related to older answer that I posted) (这与我发布的旧答案有关)

The Mono framework that is installed includes a relatively old version of NUnit (version 2.4.8). 安装的Mono框架包括相对旧版本的NUnit (版本2.4.8)。 There are a number of issues/bugs in that version that range from incorrect exception trapping to solution/project parsing problems. 该版本中存在许多问题/错误,范围从错误的异常捕获到解决方案/项目解析问题。

What we do for our OS-X builds (including Jenkins CI) is to install the latest NUnit via nuget to our solution root directory and use that installation for the local testing of the build artifacts. 我们为OS-X构建(包括Jenkins CI)所做的是通过nuget将最新的NUnit安装到我们的解决方案根目录,并使用该安装来进行构建工件的本地测试。

Something like: 就像是:

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

OK, 好,

This was quite a nasty one. 这是一个非常令人讨厌的问题。 The problem was neither related directly to Mono or NUnit. 问题既不直接与Mono或NUnit有关。 Although the older version of NUnit was causing other issues. 虽然旧版NUnit引起了其他问题。

Thanks to @SushiHangover for the tip that got me starting in resolving this problem. 感谢@SushiHangover的提示让我开始解决这个问题。

Initially I broke down the unit tests to instantiate each dependencies of the APIService class that ultimately flagged an issue with the System.Net.Http dll over the iOS, PCL and Unit test projects. 最初,我打破了单元测试,以实例化APIService类的每个依赖项,最终通过iOS,PCL和Unit测试项目标记System.Net.Http dll的问题。 It appears that one of the libraries I was implementing was referencing v1.5.0.0 of this library causing a version mismatch over the projects, this was exacerbated by incorrect references (.Net, PCL etc). 看来我正在实现的其中一个库引用了这个库的v1.5.0.0,导致项目的版本不匹配,不正确的引用(.Net,PCL等)加剧了这种情况。 I resolved this by including an specific assembly binding in each projects app.config. 我通过在每个项目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>

This solved around 80 failing unit tests but still left around 50 failing. 这解决了大约80次失败的单元测试,但仍然有50次失败。

Further poking around flagged an issue with the versions of Akavache caching library across the PCL and unit test projects which resolved another 40 unit tests. 进一步探讨了PCL上的Akavache缓存库版本和单元测试项目的问题,解决了另外40个单元测试。

Finally there was an issue with running Telerik's JustMock library in the Unit Test project where parts of the library does not appear to be supported when testing a PCL. 最后,在单元测试项目中运行Telerik的JustMock库存在一个问题,在测试PCL时,部分库似乎不受支持。 I resolved this be swapping out JustMock for Moq and refactoring some tests. 我解决了这个问题,换掉JustMock for Moq并重构一些测试。 This resolved the remaining failing unit testing with Xamarin Studio. 这解决了使用Xamarin Studio进行的剩余故障单元测试。

I then ran these tests on the build server and get 80 passing tests and 87 not run. 然后我在构建服务器上运行这些测试并获得80次通过测试,87次不运行。 Damn. 该死的。

To resolve this issue I swapped out the default test runner in Xamarin v2.4.8 for the most recent one downloaded and now all unit test pass on the build server. 为了解决这个问题,我在Xamarin v2.4.8中换掉了最新下载的默认测试运行器,现在在构建服务器上传递了所有单元测试。

To cut a long story short check you references when you get these kind of issues. 简而言之, 请查看您在遇到这些问题时的参考资料

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

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