.net - 如何在 ASP.NET Core 测试中 stub /模拟服务

标签 .net asp.net-web-api asp.net-core .net-core

我想测试 ASP.NET Web Api 项目中的一些类。我不需要通过 TestServer 进行请求响应集成测试(尽管它们很好),但我想让我的测试尽可能接近“真实的东西”。因此,我想使用启动中添加的服务来解析我的类,但在测试的基础上通过 stub /模拟更改其中一些(一些测试需要模拟,其他测试不需要)。

在过去,当 ASP.NET 没有内部依赖注入(inject)框架时,这确实很容易做到。因此,我只需调用一个将所有依赖项注册到容器的类,然后为每个测试创建子容器,将一些依赖项更改为模拟,仅此而已。

我尝试过这样的事情:

    var host = A.Fake<IHostingEnvironment>();
    var startup = new Startup(host);
    var services = new ServiceCollection();
    //Add stubs here
    startup.ConfigureServices(services);
    var provider = services.BuildServiceProvider();
    provider.GetService<IClientsHandler>();

它似乎有效,但我不想为每个测试创建整个启动基础设施。我想创建一次,然后为每个测试创建“子容器”或“子范围”。是否可以?基本上我正在寻找一种在 Startup 之外修改服务的方法。

最佳答案

在配置 HttpConfiguration 时,可以通过创建自定义 IHttpControllerActivator 来为每个请求创建子范围。

这是针对 OWIN 的,但转换为 .Net Core 应该非常简单: https://gist.github.com/jt000/eef096a2341471856e8a86d06aaec887

重要的部分是在该范围内创建范围和 Controller ......

var scope = _provider.CreateScope();
request.RegisterForDispose(scope);

var controller = scope.ServiceProvider.GetService(controllerType) as IHttpController;

...并覆盖默认的IHttpControllerActivator...

config.Services.Replace(typeof (IHttpControllerActivator), new ServiceProviderControllerActivator(parentActivator, provider));

现在您可以添加要通过具有范围依赖注入(inject)的 IServiceProvider 创建的 Controller ...

services.AddScoped<ValuesController>((sp) => new ValuesController(sp.GetService<ISomeCustomService>()));

要在单元测试中测试 ValuesController,我建议使用 Moq 框架之类的东西来模拟服务接口(interface)中的方法。例如:

var someCustomService = Mock.Of<ISomeCustomService>(s => s.DoSomething() == 3);
var sut = new ValuesController(someCustomService);

var result = sut.Get();

Assert.AreEqual(result, new [] { 3 });

关于.net - 如何在 ASP.NET Core 测试中 stub /模拟服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42536916/

相关文章:

oauth - 使用 ASP.net API 的不记名 token 身份验证

azure-sql-database - 在 Entity Framework 7/MVC 6 上动态更改连接字符串(每个请求)

c# - ASP.NET Core 表单 POST 导致 HTTP 415 Unsupported Media Type 响应

c# - CsvHelper 忽略不工作

c# - LINQ - Distinct 被忽略了吗?

c# - [Serializable] 类的 Web.Api 模型绑定(bind)不起作用

asp.net-core - 获取 ASP.NET Core 3.0 中所有注册的路由

.net - 捕获窗体的按键而不是控件的按键

c# - 使用 "Start Debugging"和 "Start Without Debugging"启动应用程序时的不同堆栈跟踪

c# - WebAPI线程