sql – 如何单元测试ServiceStack?
|
我喜欢SS,但我正在抓我的头试图单元测试我的业务层.我是新来的单元测试和模拟,并正在阅读在NSubstitute,因为这看起来像一个有趣的嘲笑层. 我的文件结构大致如下: 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指向HelloWorldService程序集,并以标准注册SQL Server数据库. 一切真的很好,我已经能够以更清洁的方式建立逻辑.不幸的是,我希望进行单元测试,但我不知道如何解耦数据库. 我试图在内存数据库中注册一个假的,但是我认为在SQL Server vs SQLite方式中,我已经使用代码来获取身份等等有不兼容的问题. // container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(":memory:",false,SqliteOrmLiteDialectProvider.Instance));
// container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(":memory:",SqlServerDialect.Provider));
我只想去耦和单元测试.有什么想法吗? *** UPDATE public class UnitTest1
{
private Container container;
[TestMethod]
public void TestMethod1()
{
container = new Container();
// container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(":memory:",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.RegisterAutoWiredAs<FeedbackRepo,IFeedbackRepo>();
// service is autowiring --> leading to good injections
container.RegisterAutoWired<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);
}
}
目前在我派生的服务类中,让’Db’停止为null. 解决方法如果要单独测试ServiceStack服务,您可以采取几种不同的方法.基本 Service类本身只是一个简单的C#类,它可以手动定义和注入依赖关系,或者使用内置的IOC容器.我们将使用这个测试这个简单服务的simple unit test example来说明这两种方法: 的DTO 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; }
}
履行 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;
}
}
此服务提供2个操作,FindRockstars使得数据库查询直接在服务类本身中,GetStatus使用存储库而不是所有的数据访问. 使用内存数据库 如果您在服务实现中直接访问Db,那么您将要使用一个真正的数据库,因为ADO.NET IDbConnection需要大量的嘲弄.您可以通过使用内置的IOC以相同的方式在ServiceStack本身注册您的依赖关系.对于单元测试,只要在TestFixtureSetup中使用新的Container,我们就可以在没有AppHost的情况下执行此操作,例如: 测试设置 private ServiceStackHost appHost;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
appHost = new BasicAppHost().Init();
var container = appHost.Container;
container.Register<IDbConnectionFactory>(
new OrmLiteConnectionFactory(":memory:",SqliteDialect.Provider));
container.RegisterAutoWiredAs<RockstarRepository,IRockstarRepository>();
container.RegisterAutoWired<SimpleService>();
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
db.DropAndCreateTable<Rockstar>();
db.InsertAll(SeedData);
}
}
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
appHost.Dispose();
}
随着所有设置,我们现在可以独立于ServiceStack本身,隔离测试服务就像一个普通的C#类: [Test]
public void Using_in_memory_database()
{
//Resolve the autowired 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" }));
}
手动注入依赖关系 如果您希望单元测试不使用内存数据库,您可以选择模拟您的依赖项.在这个例子中,我们将使用一个独立的Mock,但是可以使用像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.True);
Assert.Throws<HttpError>(() =>
service.Get(new GetStatus { LastName = "Hendrix" }));
}
当我们手动注入所有依赖项时,此示例不需要容器.我也把这个例子添加到了Testing wiki文档中. (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
