Siento que me estoy perdiendo algo realmente obvio aquí. Tengo clases que requieren la inyección de opciones usando el patrón .Net Core IOptions (?). Cuando voy a la prueba unitaria de esa clase, quiero burlarme de varias versiones de las opciones para validar la funcionalidad de la clase. ¿Alguien sabe cómo burlarse / instanciarse / poblar correctamente IOptions fuera de la clase de inicio?
Aquí hay algunas muestras de las clases con las que estoy trabajando:
Configuraciones / Opciones Modelo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace OptionsSample.Models
{
public class SampleOptions
{
public string FirstSetting { get; set; }
public int SecondSetting { get; set; }
}
}
Clase a probar que utiliza la configuración:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using OptionsSample.Models
using System.Net.Http;
using Microsoft.Extensions.Options;
using System.IO;
using Microsoft.AspNetCore.Http;
using System.Xml.Linq;
using Newtonsoft.Json;
using System.Dynamic;
using Microsoft.Extensions.Logging;
namespace OptionsSample.Repositories
{
public class SampleRepo : ISampleRepo
{
private SampleOptions _options;
private ILogger<AzureStorageQueuePassthru> _logger;
public SampleRepo(IOptions<SampleOptions> options)
{
_options = options.Value;
}
public async Task Get()
{
}
}
}
Prueba unitaria en un ensamblaje diferente de las otras clases:
using OptionsSample.Repositories;
using OptionsSample.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
namespace OptionsSample.Repositories.Tests
{
public class SampleRepoTests
{
private IOptions<SampleOptions> _options;
private SampleRepo _sampleRepo;
public SampleRepoTests()
{
//Not sure how to populate IOptions<SampleOptions> here
_options = options;
_sampleRepo = new SampleRepo(_options);
}
}
}
IOptions<T>
que solo tengas que burlarteValue
de devolver la clase que deseasRespuestas:
Necesita crear y rellenar manualmente un
IOptions<SampleOptions>
objeto. Puede hacerlo a través de laMicrosoft.Extensions.Options.Options
clase auxiliar. Por ejemplo:Puede simplificar eso un poco para:
Obviamente esto no es muy útil como es. Deberá crear y completar un objeto SampleOptions y pasarlo al método Create.
fuente
new OptionsWrapper<SampleOptions>(new SampleOptions());
todas partesSi tiene la intención de utilizar Mocking Framework como lo indica @TSeng en el comentario, debe agregar la siguiente dependencia en su archivo project.json.
Una vez que se restaura la dependencia, usar el marco MOQ es tan simple como crear una instancia de la clase SampleOptions y luego, como se mencionó, asignarla al Valor.
Aquí hay un resumen del código de cómo se vería.
Una vez que el simulacro está configurado, ahora puede pasar el objeto simulado al contructor como
HTH
Para su información, tengo un repositorio git que describe estos 2 enfoques en Github / patvin80
fuente
Puede evitar usar MOQ en absoluto. Úselo en su archivo de configuración de pruebas .json. Un archivo para muchos archivos de clase de prueba. Estará bien usarlo
ConfigurationBuilder
en este caso.Ejemplo de appsetting.json
Ejemplo de clase de mapeo de configuraciones:
Ejemplo de servicio que se necesita para probar:
Clase de prueba NUnit:
fuente
Clase dada
Person
que depende dePersonSettings
lo siguiente:IOptions<PersonSettings>
se puede burlar yPerson
probar de la siguiente manera:Para inyectar
IOptions<PersonSettings>
enPerson
lugar de pasarlo explícitamente al ctor, use este código:fuente
Siempre puede crear sus opciones a través de Options.Create () y luego simplemente usar AutoMocker.Use (options) antes de crear la instancia simulada del repositorio que está probando. El uso de AutoMocker.CreateInstance <> () facilita la creación de instancias sin pasar parámetros manualmente
He cambiado un poco tu SampleRepo para poder reproducir el comportamiento que creo que quieres lograr.
fuente
Aquí hay otra forma fácil que no necesita Mock, sino que usa el OptionsWrapper:
fuente
Para mis pruebas de sistema e integración, prefiero tener una copia / enlace de mi archivo de configuración dentro del proyecto de prueba. Y luego uso el ConfigurationBuilder para obtener las opciones.
De esta manera puedo usar la configuración en todas partes dentro de mi TestProject. Para las pruebas unitarias, prefiero usar MOQ como se describe en patvin80.
fuente
De acuerdo con Aleha en que usar un archivo de configuración testSettings.json es probablemente mejor. Y luego, en lugar de inyectar la IOption, simplemente puede inyectar las SampleOptions reales en el constructor de su clase, cuando la unidad pruebe la clase, puede hacer lo siguiente en un dispositivo fijo o de nuevo solo en el constructor de la clase de prueba:
fuente