如何在ASP.NET Core测试中存根/模拟服务

Sib*_*Guy 15 .net asp.net-web-api .net-core asp.net-core

我想测试一些属于ASP.NET Web Api项目的类.我不需要通过TestServer进行请求 - 响应集成测试(虽然它们很好)但我想让我的测试尽可能接近"真实的东西".所以我想使用Startup中添加的服务来解析我的类,但是在测试的基础上通过存根/模拟更改其中的一些(一些测试需要模拟,其他测试则不需要).

在ASP.NET没有内部依赖注入框架的过去,很容易做到这一点.所以我只需要调用一个将所有依赖项注册到容器的类,然后为每个测试创建子容器,将一些依赖项更改为mocks,就是这样.

我试过这样的事情:

    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>();
Run Code Online (Sandbox Code Playgroud)

它似乎工作,但我不想为每个测试创建整个启动基础设施.我想创建它一次,然后为每个测试创建"子容器"或"子范围".可能吗?基本上我正在寻找一种方法来修改Startup之外的服务.

Tse*_*eng 2

文档中对此进行了详细介绍。

对于集成测试,您使用TestServer类并给它一个Startup类(不一定是实时启动,也可以是StartupIntegrationTest或通过Configure{Envrionment Name here}/ConfigureServices{Envrionment Name here}方法启动。

 var server = new TestServer(new WebHostBuilder()
    .UseStartup<Startup>()
    // this would cause it to use StartupIntegrationTest class or ConfigureServicesIntegrationTest / ConfigureIntegrationTest methods (if existing)
    // rather than Startup, ConfigureServices and Configure 
    .UseEnvironment("IntegrationTest")); 
Run Code Online (Sandbox Code Playgroud)

要访问服务提供商,请执行以下操作

var server = new TestServer(new WebHostBuilder()
    .UseStartup<Startup>()
    .UseEnvironment("IntegrationTest")); 
var controller = server.Host.Services.GetService<MyService>();
Run Code Online (Sandbox Code Playgroud)

对于单元测试,您根本不应该使用IServiceCollection/ ,只需模拟接口并注入它们。IServiceProvider

  • 单元测试和集成测试之间没有二元划分。两者之间存在巨大的灰色地带。如果我有成熟的集成测试,但在某些情况下我想模拟一些依赖项(即不发送真实的电子邮件),我的测试仍然是集成测试。 (3认同)