¿Cómo probar UnitStack?

Me encanta SS, pero me estoy rascando la cabeza tratando de probar mi capa de negocios. Soy nuevo en la testing unitaria y en la grabación y he estado leyendo en NSubstitute, ya que parece una divertida capa de burla.

Tengo mi estructura de files más o less así:

MainAppHostProject* | -AppStart -AppHost <-- standard apphost DtoProject* | -HelloWorldDto <-- simple POCO to ServiceLayerProject* | -HelloWorldService <-- service interface that merely passes/sends Dtos to/from business layer BusinessLayerProject* | -HelloWorldManager <-- logic to construct response and this class extends 'Service' (letting me access Db, session, etc)...sidenote: maybe i shouldve called this a HelloWorldRepository? -CustomAuthProvider -CustomUserSession DaoProject* | -HelloWorldDao <-- POCO of table structure 

Apphost apunta al set HelloWorldService y registra la database SQL Server como estándar.

En realidad, todo funciona muy bien y he podido desarrollar la lógica de una manera más limpia. Desafortunadamente, deseo realizar testings unitarias PERO no sé cómo desacoplar la database.

Traté de registrar una database falsa en la memory, pero luego creo que hay problemas de incompatibilidad con la forma en que he usado el código para get identidades, etc. en SQL Server frente a forms SQLite.

 // container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(":memory:", false, SqliteOrmLiteDialectProvider.Instance)); // container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(":memory:", false, SqlServerDialect.Provider)); 

Solo quiero desacoplarme y probar la unidad. Alguna idea, por favor?

***ACTUALIZAR

 public class UnitTest1 { private Container container; [TestMethod] public void TestMethod1() { container = new Container(); // container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(":memory:", false, SqliteDialect.Provider)); // sqlite didnt work so attempting with a real DB for now var connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=XXX;Integrated Security=True"; container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider)); // dependencies are injecting ok container.RegisterAutoWinetworkingAs<FeedbackRepo, IFeedbackRepo>(); // service is autowiring --> leading to good injections container.RegisterAutoWinetworking<FeedbackService>(); var service = container.Resolve<FeedbackService>(); service.SetResolver(new BasicResolver(container)); // unit test is working well var request = new DTO.FeedbackDto { Message = "test" }; bool result = service.Post(request); } } 

Por el momento trato de hacer que 'Db' deje de ser nulo en mis classs de services derivados.

Si desea probar un service ServiceStack de forma aislada, hay un par de enfoques diferentes que puede tomar. La class de service base en sí es simplemente una class C # simple que le permite definir e inyectar dependencies manualmente o mediante el uso del contenedor IOC incorporado.

Ilustraremos ambos enfoques utilizando este ejemplo de testing de unidad simple que testing este service simple:

DTOs

 public class FindRockstars { public int? Aged { get; set; } public bool? Alive { get; set; } } public class GetStatus { public string LastName { get; set; } } public class RockstarStatus { public int Age { get; set; } public bool Alive { get; set; } } public class Rockstar { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int? Age { get; set; } } 

Implementación

 public class SimpleService : Service { public IRockstarRepository RockstarRepository { get; set; } public List<Rockstar> Get(FindRockstars request) { return request.Aged.HasValue ? Db.Select<Rockstar>(q => q.Age == request.Aged.Value) : Db.Select<Rockstar>(); } public RockstarStatus Get(GetStatus request) { var rockstar = RockstarRepository.GetByLastName(request.LastName); if (rockstar == null) throw HttpError.NotFound("'{0}' is not a Rockstar".Fmt(request.LastName)); var status = new RockstarStatus { Alive = RockstarRepository.IsAlive(request.LastName) }.PopulateWith(rockstar); //Populates with matching fields return status; } } 

Este service proporciona 2 operaciones, FindRockstars que realiza consultas de db directamente en la class de service en sí, y GetStatus que utiliza un repository en su lugar para todo su acceso a datos.

Usando una database en memory

Si está accediendo a Db directamente desde la implementación de su service, querrá utilizar una database real dado ADO.NET IDbConnection requiere un gran esfuerzo para burlarse. Puede hacer esto de la misma manera que registraría sus dependencies en ServiceStack, utilizando el IOC incorporado. Para una testing unitaria, podemos hacer esto sin un AppHost con solo usar un nuevo Container en su TestFixtureSetup , por ejemplo:

Configuración de testing

 private ServiceStackHost appHost; [TestFixtureSetUp] public void TestFixtureSetUp() { appHost = new BasicAppHost().Init(); var container = appHost.Container; container.Register<IDbConnectionFactory>( new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider)); container.RegisterAutoWinetworkingAs<RockstarRepository, IRockstarRepository>(); container.RegisterAutoWinetworking<SimpleService>(); using (var db = container.Resolve<IDbConnectionFactory>().Open()) { db.DropAndCreateTable<Rockstar>(); db.InsertAll(SeedData); } } [TestFixtureTearDown] public void TestFixtureTearDown() { appHost.Dispose(); } 

Con todo configurado, ahora podemos probar el service como una class normal de C # aislada independientemente de ServiceStack:

 [Test] public void Using_in_memory_database() { //Resolve the autowinetworking service from IOC and set Resolver for the base class var service = appHost.Container.Resolve<SimpleService>(); var rockstars = service.Get(new FindRockstars { Aged = 27 }); rockstars.PrintDump(); //Print a dump of the results to Console Assert.That(rockstars.Count, Is.EqualTo(SeedData.Count(x => x.Age == 27))); var status = service.Get(new GetStatus { LastName = "Vedder" }); Assert.That(status.Age, Is.EqualTo(48)); Assert.That(status.Alive, Is.True); status = service.Get(new GetStatus { LastName = "Hendrix" }); Assert.That(status.Age, Is.EqualTo(27)); Assert.That(status.Alive, Is.False); Assert.Throws<HttpError>(() => service.Get(new GetStatus { LastName = "Unknown" })); } 

Injerto manual de dependencies

Si prefiere que las testings de su unidad no utilicen una database en memory, puede elegir simular sus dependencies. En este ejemplo usaremos un simulacro independiente, pero puede networkingucir el text repetitivo usando una biblioteca burlona como Moq .

 public class RockstarRepositoryMock : IRockstarRepository { public Rockstar GetByLastName(string lastName) { return lastName == "Vedder" ? new Rockstar(6, "Eddie", "Vedder", 48) : null; } public bool IsAlive(string lastName) { return lastName == "Grohl" || lastName == "Vedder"; } } [Test] public void Using_manual_dependency_injection() { var service = new SimpleService { RockstarRepository = new RockstarRepositoryMock() }; var status = service.Get(new GetStatus { LastName = "Vedder" }); Assert.That(status.Age, Is.EqualTo(48)); Assert.That(status.Alive, Is.True); Assert.Throws<HttpError>(() => service.Get(new GetStatus { LastName = "Hendrix" })); } 

Este ejemplo no necesita un contenedor ya que estamos inyectando todas las dependencies manualmente. También agregué este ejemplo a los documentos de testing wiki .

    Intereting Posts