如何最好地对使用 IServiceGateway 调用其他内部服务的 ServiceStack 服务进行单元测试

How best to unit test a ServiceStack service that uses IServiceGateway to call other internal services

我一直在遵循此处的指南 - https://docs.servicestack.net/testing

我正在尝试进行单元测试而不是集成,只是为了减少模拟和其他复杂性的级别。

我的一些服务通过推荐的 IServiceGateway API 调用我的一些其他服务,例如Gateway.Send(我的请求).

然而,当 运行 测试时,我得到 System.NotImplementedException:“无法解析服务 'GetMyContentRequest'”。

我使用了 container.RegisterAutoWired() 来处理这个请求。

我不确定下一步该去哪里。我真的不想重新开始设置集成测试模式。

如果您尝试将服务集成作为单元测试而不是在经过验证的有效状态下启动的集成测试来执行,您可能会不断地 运行 遇到问题。

但对于网关请求,它们是使用 IServiceGateway 执行的,您可以选择在自定义 AppHost 中使用自定义实现覆盖 implementing GetServiceGateway(),或者通过注册IServiceGatewayFactoryIServiceGateway 在您的 IOC 中,这是默认实现:

public virtual IServiceGateway GetServiceGateway(IRequest req)
{
    if (req == null)
        throw new ArgumentNullException(nameof(req));

    var factory = Container.TryResolve<IServiceGatewayFactory>();
    return factory != null ? factory.GetServiceGateway(req) 
        : Container.TryResolve<IServiceGateway>()
        ?? new InProcessServiceGateway(req);
}

根据@mythz的回答中的讨论,我的解决方案是:

像 OP 这样的用例:测试“主”服务,模拟“子服务”,像 OP 我想用单元测试(所以 BasicAppHost)来做,因为它更快,我相信以这种方式模拟服务更容易(旁注:对于基于 AppHost 的集成测试,SS 将扫描程序集以查找(真实)服务,那么如何模拟?从“容器”注销并替换 w.mock?)。

无论如何,对于单元测试:

我的“主要”服务正在使用另一个服务,通过 IServiceGateway(这是官方推荐的方式):

public MainDtoResponse Get(MainDto request) {
  // do some stuff
  var subResponse = Gateway.Send(new SubDto { /* params */ });
  // do some stuff with subResponse
}

在我的测试设置中:

appHost = new BasicAppHost().Init();

var mockGateway = new Mock<IServiceGateway>(); // using Moq
mockGateway.Setup(x => x.Send<SubDtoResponse>(It.IsAny<SubDto>()))
  .Returns(new SubDtoResponse { /* ... */ });
container.Register(mockGateway.Object);

所以必须mock IServiceGateway,然后是Send方法。我做错的是在我应该模拟网关的时候模拟了服务。

然后以正常方式调用主服务(正在测试)进行单元测试,如文档中所述:

var s = appHost.Container.Resolve<MainService>(); // must be populated in DI manually earlier in code
s.Get(new MainDto { /* ... */ })

PS:mockGateway.Setup可以在每个测试里面使用,不一定在OneTimeSetUp.