c# unit-testing xamarin mono xamarin.ios

c# - NUnit y prueba una PCL de Xamarin



unit-testing mono (2)

DE ACUERDO,

Esto fue bastante desagradable. El problema no estaba relacionado directamente con Mono o NUnit. Aunque la versión anterior de NUnit causaba otros problemas.

Gracias a @SushiHangover por la sugerencia que me ayudó a comenzar a resolver este problema.

Inicialmente analicé las pruebas unitarias para crear instancias de cada dependencia de la clase APIService que finalmente marcó un problema con System.Net.Http dll en los proyectos de prueba de iOS, PCL y Unit. Parece que una de las bibliotecas que estaba implementando hacía referencia a v1.5.0.0 de esta biblioteca, lo que causaba una falta de coincidencia de versión en los proyectos, lo que se vio agravado por referencias incorrectas (.Net, PCL, etc.). Resolví esto al incluir un enlace de ensamblaje específico en cada aplicación de proyectos .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>

Esto resolvió alrededor de 80 pruebas de unidades fallidas, pero aún dejó alrededor de 50 fallas.

Además, se detectó un problema con las versiones de la biblioteca de almacenamiento en caché de Akavache en todo el PCL y los proyectos de pruebas unitarias que resolvieron otras 40 pruebas unitarias.

Finalmente hubo un problema con la ejecución de la biblioteca JustMock de Telerik en el proyecto Unit Test, donde partes de la biblioteca no parecen ser compatibles cuando se prueba una PCL. Resolví que esto sería intercambiar JustMock por Moq y refactorizar algunas pruebas. Esto resolvió las pruebas restantes de unidades fallidas con Xamarin Studio.

Luego realicé estas pruebas en el servidor de compilación y obtuve 80 pruebas de aprobación y 87 no se ejecutaron. Maldita sea.

Para resolver este problema, cambié el corredor de prueba predeterminado en Xamarin v2.4.8 por el más reciente descargado y ahora todas las pruebas de unidad pasan al servidor de compilación.

Para abreviar , haga una breve reseña de las referencias que recibe cuando obtiene este tipo de problemas.

Estoy desarrollando una biblioteca de clases portátil y una aplicación iOS donde el acceso a los datos se basa en las bibliotecas ModernHttpClient , Fusillade , Refit y Akavache de Paul Betts . Esto funciona en las aplicaciones PCL e iOS, pero estoy teniendo problemas al crear pruebas unitarias contra PCL.

Si utilizo la prueba Resharper que se ejecuta en Visual Studio 2015, todas mis pruebas pasan, pero si ejecuto las pruebas NUnit en Xamarin Studio, la mitad de las pruebas fallan con TypeLoadExceptions . He intentado determinar qué dll me está causando los problemas pero, por lo que puedo ver, todo es como debería ser.

Clase PCL bajo prueba

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; }

Estudio fallido de Xamarin Studio

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

Resultado de la prueba

Esperado: Pero fue: (No se pudo cargar el tipo ''ApiService`1'' del ensamblado ''/Users/206474978/Desktop/test/test/test/bin/Debug/xxx.xxx.xxx.dll'') en NUnit.Framework. Assert.Throws (expresión IResolveConstraint, código NUnit.Framework.TestDelegate, mensaje System.String, System.Object [] args) <0x377c1c8 + 0x000e6> en: 0

en NUnit.Framework.Assert.That (System.Object actual, expresión de IResolveConstraint, mensaje System.String, System.Object [] args) <0x377c888 + 0x000bf> en: 0 en NUnit.Framework.Assert.Throws (expresión IResolveConstraint, NUnit .Framework.TestDelegate code, System.String message, System.Object [] args) <0x377c1c8 + 0x00137> in: 0
en NUnit.Framework.Assert.Throws (System.Type expectedExceptionType, NUnit.Framework.TestDelegate code, System.String message, System.Object [] args) <0x377bfc8 + 0x0004f> en: 0
en NUnit.Framework.Assert.Throws [T] (NUnit.Framework.TestDelegate code, System.String message, System.Object [] args) <0x377bf58 + 0x00033> en: 0 en NUnit.Framework.Assert.Throws [T] (Código de NUnit.Framework.TestDelegate) <0x377bf08 + 0x0003b> en: 0 en test.Test + ApiServiceTest.PassingInANullBaseUrlThrowsAnException () [0x00001] en /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 &) en System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System. Carpeta Reflection.Binder, parámetros System.Object [], System.Globalization.CultureInfo culture) [0x00038] en /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

Ahora, esto normalmente no sería un problema ya que solo usaría reshaper, pero estoy creando nuestra cartera de Integración Continua sobre Jenkins y ejecutando las pruebas a través del paquete nunit dentro de las bibliotecas de Xamarin, lo que da como resultado las fallas en el informe de compilación.

¿Alguna idea de cuál es el problema aquí?

ACTUALIZAR

Ok, después de seguir el consejo de SushiHangover utilicé la última versión del corrector de prueba NUnit y obtuve el siguiente resultado. Parece que los errores son TypeLoadException o BadImageFormatException, pero no estoy seguro de por qué. Revisé el resultado de ambos proyectos y ambos están configurados en 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); }

Tipo no válido xxx.xxx.Core.Services.Lib.ApiService`1 por ejemplo campo 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

ACTUALIZACIÓN 2

Otra prueba falla con la stacktrace siguiente, esto parece un problema con mono?

System.TypeLoadException: no se pudo cargar el tipo ''ApiService`1'' del ensamblado ''/Users/206474978/Documents/Development/Projects/BRSMemberApp/UnitTests/BrsGolf.Members.Core.Tests/bin/Debug/Brs.Members.Core.dll ''.

at (wrapper managed-to-native) System.Reflection.MonoMethod: InternalInvoke (System.Reflection.MonoMethod, object, object [], System.Exception &) en System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, Carpeta System.Reflection.Binder, parámetros System.Object [], System.Globalization.CultureInfo culture) [0x00038] en /private/tmp/source-mono-4.2.3/bockbuild-mono-4.2.0-branch/profiles/ mono-mac-xamarin / build-root / mono-4.2.3 / mcs / clase / corlib / System.Reflection / MonoMethod.cs: 295


(Esto está relacionado con la respuesta anterior que publiqué)

El framework Mono que está instalado incluye una versión relativamente anterior de NUnit (versión 2.4.8). Hay una serie de problemas / errores en esa versión que van desde interceptación de excepción incorrecta hasta problemas de análisis de solución / proyecto.

Lo que hacemos para nuestras versiones de OS-X (incluido Jenkins CI) es instalar la última NUnit a través de Nuget en nuestro directorio raíz de soluciones y usar esa instalación para las pruebas locales de los artefactos de construcción.

Algo como:

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