在使用NUnit对ServiceStack.OrmLite进行单元测试时,如何将Db注入Service类?

时间:2013-01-09 19:03:25

标签: nunit inversion-of-control ormlite-servicestack

我对使用ServiceStack创建的一些服务类编写单元测试(使用NUnit)感兴趣,使用“New API”(继承自ServiceStack.ServiceInterface.Service)。当使用AppHost在ASP.NET应用程序中托管时,服务的Db属性是正确自动连接的,但是当在该环境之外运行时,我似乎无法弄清楚正确的技术。我在ServiceStack中看到了各种与测试相关的命名空间和类,但是找不到注入服务的Db属性的明确示例,而不是简单地直接设置连接工厂然后调用各种IDbConnection扩展方法(Insert ,选择等。)。

我试过让我的测试类继承自ServiceStack.ServiceInterface.Testing.TestBase并重写其Configure方法来注册IDbConnectionFactory(使用“:memory:”),以及在我的TestFixtureSetUp中设置OrmLiteConfig.DialectProvider = SqliteDialect.Provider;,但是在调用我的服务方法时(在ServiceStack.ServiceInterface.Service.get_Db()处),我继续得到NullReferenceException。似乎Funq容器没有自动连接任何东西。

SQLite本身已经正确设置,我可以通过更简单的单元测试来确认,这些单元测试绕过我的服务类并且只是直接进行IDbConnection调用。

我错过了什么?

修改

单元测试ServiceStack服务似乎需要存在主机和客户端,尽管看起来有办法设置它以避免序列化成本(使用DirectServiceClient,如图here所示) - 虽然我没有成功地让我的工作在我的情况下。我设法使用AppHostHttpListenerBase方法(参见here)来实现这一点,尽管它更像是集成测试而不是单元测试(因此速度较慢)。

1 个答案:

答案 0 :(得分:5)

docs on Testing显示了几种注入依赖关系的不同方法。

如果您查看基础Service的实现,它只会从IDbConnectionFactory创建 Db

private IDbConnection db;
public virtual IDbConnection Db
{
    get { return db ?? (db = TryResolve<IDbConnectionFactory>().OpenDbConnection()); }
}

它只是从本地或全球IResolver IOC容器解析:

public static IResolver GlobalResolver { get; set; }

private IResolver resolver;
public virtual IResolver GetResolver()
{
    return resolver ?? GlobalResolver;
}

public virtual T TryResolve<T>()
{
    return this.GetResolver() == null
        ? default(T)
        : this.GetResolver().TryResolve<T>();
}

因此,要注入自己的依赖项(使用Service基类时),您只需要配置一个IAppHost,其中包含您可以使用的服务所需的依赖项:

using (var appHost = new BasicAppHost {
    ConfigureContainer = c => {
        c.Register<IDbConnectionFactory>(new ...);
    }
}.Init())
{
  //...    
}

然后,您可以根据自己的服务需要设置自己的服务,例如:

var service = appHost.ResolveService<MyService>();

哪个将自动装配AppHost中配置的所有依赖项,您还可以通过正常的属性访问添加自己的特定于测试的依赖项,例如:

var service.MyDependency = new Mock<IMyDependency>().Object;

从那时起,你可以按照惯例调用和测试你的C#类方法:

var response = service.Get(new RequestDto { ... });
Assert.That(response.Result, Is.Equal("Expected Result from DB"));