【问题标题】:Unit test ServiceStack services in ServiceStack 3.9.71在 ServiceStack 3.9.71 中对 ServiceStack 服务进行单元测试
【发布时间】:2017-01-26 09:09:08
【问题描述】:

我最近完成了一个 .Net 项目,该项目通过 ServiceStack(3.9.71) REST API 从 Microsoft SQL 数据库公开 DAO。因为我要重构一些部分,所以我想对(至少)所有的 servicestack 服务进行单元测试。为了更好地理解,我快速草拟了实现的工作原理。

每个服务都包含一个DBService 类型的属性,它封装了所有 服务的所有 数据库访问。不幸的是,这是一个很难模拟的具体类。 DI.Container 包装了 ServiceStack 的 IOC

public class SomeService : Service
{
    public DBService { get { return DI.Container.Resolve<DBService>(); } } 

    public object Get(SomeDataClass class)
    {
       var response = DBService.SomeServiceGet();
       return response;
    }

    // other code omitted

}

DBService 看起来像这样(草稿):

public class DBService 
{
     public IDbConnectionFactory DBFactory { get { return DI.Container.Resolve<IDbConnectionFactory>(); } }
    public SomeServiceResponse SomeServiceGet()
    {
       //DB Access here...
       // ...
    }
    public SomeOtherServiceResponse SomeOtherServiceGet()
    {
       //...
    }

    // following about 30 other methods for all the services (POST,GET,PUT etc)
}

我阅读了对此question 的详细回复,但我无法在ServiceStack 3.9.71 中创建和初始化BasicAppHost,因为它立即抛出了System.TypeLoadExceptionMethod 'get_VirtualPathProvider'

另一方面,我认为我实际上并不需要BasicAppHost。我只需要对DBService 进行单元测试,然后使用某种模拟的DBService 对servicestack 服务进行单元测试。我唯一的问题是DBService 不是一个接口,实际上我不确定如何处理(模拟)SQL 数据库和IOC

[更新]

不幸的是,我仍然无法测试服务,因为我不能只 new 测试中的服务。如果我这样做,我会得到:

System.TypeLoadException 无法从程序集中加载类型“ServiceStack.ServiceHost.IService”

这是我的测试:

[Fact]
public void SomeDataTest()
{
   var serviceUnderTest = new SomeService();
   var response = serviceUnderTest.Get(new SomeDataClass());

   Assert.NotNull(response);
}

我想问题是服务强烈使用了很多通过 IOC 注入的属性。我怎么能嘲笑它?创建BasicAppHost 并从那里检索服务也不起作用,我已经提到过。

【问题讨论】:

  • 一旦有问题的类都没有被密封,那么您可以创建自己的类来继承它们并覆盖或更新测试所需的行为。这很难模拟,但并非不可能。
  • 所以我其实不用关心IDbConnectionFactory的IOC注入?我也想知道它是否是一种更好的方法,所以为DBService 实现一个接口,这样我就可以轻松地模拟它。
  • 是的,抽象 DbService 将大大提高可测试性,您应该考虑将构造函数注入与您正在使用的 Service Locator 反模式相对应
  • 显示失败的单元测试。以及任何相关类作为minimal reproducible example,可用于重现问题以找到解决方案。

标签: c# unit-testing servicestack moq xunit


【解决方案1】:

如果你只是测试你的服务类,那么你可以直接模拟任何依赖:

[Fact]
public void SomeDataTest(
{
    var serviceUnderTest = new SomeService();

    var logger = new Mock<ILogger>();  // Rhino mocks fashion.
    serviceUnderTest.Logger = logger.Object;

    var response = serviceUnderTest.Get(new SomeDataClass());

   Assert.NotNull(response);
}

他们的旧文档here 中有一个关于集成测试的页面,以防您想测试AppHost

编辑:有一个模拟服务依赖的例子here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-30
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多