如果您想单独对 ServiceStack 服务进行单元测试,可以采用几种不同的方法。基地Service https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Service.cs类本身只是一个简单的 C# 类,它允许您手动或使用内置 IOC 容器定义和注入依赖项。
我们将使用这个来说明这两种方法简单的单元测试示例 https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/UnitTestExample.cs测试这个简单的服务:
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; }
}
执行
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 http://msdn.microsoft.com/en-us/library/system.data.idbconnection.aspx需要付出很大的努力来嘲笑。您可以使用内置 IOC,以与在 ServiceStack 本身中注册依赖项相同的方式执行此操作。对于单元测试,我们可以在没有 AppHost 的情况下通过使用新的Container
在你的TestFixtureSetup
, e.g:
测试设置
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();
}
完成所有设置后,我们现在可以像普通的 C# 类一样独立于 ServiceStack 本身来测试服务:
[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" }));
}
手动注入依赖
如果您不希望单元测试使用内存数据库,则可以选择模拟依赖项。在此示例中,我们将使用独立的模拟,但您可以通过使用模拟库来减少样板文件,例如Moq https://github.com/Moq/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" }));
}
此示例不需要容器,因为我们手动注入所有依赖项。我还将此示例添加到测试维基 https://github.com/ServiceStack/ServiceStack/wiki/Testing docs.