我们假设我们的服务会调用ServiceStack中的其他服务。
从阅读中,这就是人们如何称呼另一项服务:
public class CompanyService : Service
{
public SetupCompanyResponse Any(SetupCompany request)
{
var employeeService = base.ResolveService<EmployeeService>();
// Do something with employeeService
var response = employeeService.Any(new SetupEmployees());
return new SetupCompanyResponse { NumOfEmployeesCreated = response.Count };
}
}
问题:如果我是单位测试公司服务,如何模拟EmployeeService?
我能想到的最简单方法是生成一个IEmployeeService接口,以便它可以轻松模拟。但是,我不确定base.ResolveService<T>
是否能够正确地解析和自动连接ServiceStack服务,而不是给定其接口,如下所示:
var employeeService = base.ResolveService<IEmployeeService>();
特别是当我们以这种方式注册服务时(我假设是根据具体类配置对象解析,而不是像IEmployeeService
这样的接口)
public HelloAppHost() : base("Hello Web Services", typeof(HelloService).Assembly) { }
更新
显然,我可以通过以下方式实现这一目标:
1)将服务接口注册到其实现
public static void SetupServices(Container container)
{
container.RegisterAs<EmployeeService, IEmployeeService>();
}
2)使用相同的确切代码来解决,除了现在我传入接口。该服务已成功解决。
var employeeService = base.ResolveService<IEmployeeService>();
3)我现在需要做的就是覆盖解析器,服务依赖应该是完全可以模拟的。
问题:这也是一种有效的方法吗?为什么或为什么不呢?
答案 0 :(得分:2)
ServiceStack的Service class解析了IResolver的所有依赖关系,定义如下:
public interface IResolver
{
T TryResolve<T>();
}
这可以通过实现看到的多种方式注入到ServiceStack的Service类中:
public class Service : IService, IServiceBase, IDisposable
{
public static IResolver GlobalResolver { get; set; }
private IResolver resolver;
public virtual IResolver GetResolver()
{
return resolver ?? GlobalResolver;
}
public virtual Service SetResolver(IResolver resolver)
{
this.resolver = resolver;
return this;
}
public virtual T TryResolve<T>()
{
return this.GetResolver() == null
? default(T)
: this.GetResolver().TryResolve<T>();
}
...
}
您可以使用它来控制服务如何解决依赖关系。
单元测试服务的简单方法是使用Testing wiki上的BasicAppHost
,即:
appHost = new BasicAppHost().Init();
var container = appHost.Container;
container.Register<IDbConnectionFactory>(
new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider));
container.RegisterAutoWired<CompanyService>();
container.RegisterAutoWiredAs<StubEmployeeService, EmployeeService>();
其中StubEmployeeService
是EmployeeService的存根实现,例如:
public class StubEmployeeService : EmployeeService
{
public SetupEmployeesResponse Any(SetupEmployees request)
{
return new SetupEmployeesResponse { ... };
}
}
如果您更喜欢使用自己的模拟库,也可以使用任何注册方法ServiceStack's IOC Supports注册服务。