[英]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.