C# 使用ASP.NET Core 2.0集成测试HttpClient如何模拟DateTime。现在使用依赖项注入
在.NETCore2.0框架中使用依赖注入和httpClient时,我编写了两个单元测试。 我一直在这样测试我的控制器:C# 使用ASP.NET Core 2.0集成测试HttpClient如何模拟DateTime。现在使用依赖项注入,c#,unit-testing,dependency-injection,mocking,asp.net-core-2.0,C#,Unit Testing,Dependency Injection,Mocking,Asp.net Core 2.0,在.NETCore2.0框架中使用依赖注入和httpClient时,我编写了两个单元测试。 我一直在这样测试我的控制器: var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null); var controller = new ProductionLineController(mockProductionLineProvider); var mockin
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
var controller = new ProductionLineController(mockProductionLineProvider);
var mockingDate = new DateTime(date.Year, date.Month, date.Day, 12, 00, 00);
__constantsMock.Setup(x => x.GetCurrentDateTime()).Returns(mockingDate);
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
但现在我想模拟一个物体,在互联网上搜索了一下后,我能找到的就是这样做:
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
var controller = new ProductionLineController(mockProductionLineProvider);
var mockingDate = new DateTime(date.Year, date.Month, date.Day, 12, 00, 00);
__constantsMock.Setup(x => x.GetCurrentDateTime()).Returns(mockingDate);
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
这不是测试路由,最重要的是我必须创建很多对象。所以我不想这样嘲笑我的对象。
我希望能够用一个模拟对象替换服务,因为我还没有找到将IServiceCollection放入unittest方法的方法
我希望能够做到以下几点:
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
var controller = new ProductionLineController(mockProductionLineProvider);
var mockingDate = new DateTime(date.Year, date.Month, date.Day, 12, 00, 00);
__constantsMock.Setup(x => x.GetCurrentDateTime()).Returns(mockingDate);
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
我希望你能帮助我想出一个解决方案,不需要我创建每一个我正常注入的对象
先谢谢你
编辑:
我确实在做集成测试,我想测试一切,但我需要能够配置来自DateTime的结果。现在,我用一个函数创建了constants类来返回DateTime。现在,我试图模拟/存根该类/函数。这样我就可以测试可能发生的多个场景。您正在查看模拟的标准方式;您为所有依赖项创建存根(您需要能够控制所有依赖项!)并创建控制器。能够模仿DI框架并不能真正为您带来任何好处;在构建类时,仍然需要向类提供所有依赖项 使用模拟库,如NSubstitute,使其更容易;如果您觉得您有太多的依赖项,那么我怀疑您需要重构您的设计(可能控制器做得太多)
请注意,使用实际HTTP请求进行测试更像是一种集成测试;您正在测试整个应用程序,而不是一个类。在这种情况下,您可以为您的程序设置不同的环境,并使用您需要的任何额外模拟/测试数据设置注入器。您正在查看模拟的标准方式;您为所有依赖项创建存根(您需要能够控制所有依赖项!)并创建控制器。能够模仿DI框架并不能真正为您带来任何好处;在构建类时,仍然需要向类提供所有依赖项 使用模拟库,如NSubstitute,使其更容易;如果您觉得您有太多的依赖项,那么我怀疑您需要重构您的设计(可能控制器做得太多)
请注意,使用实际HTTP请求进行测试更像是一种集成测试;您正在测试整个应用程序,而不是一个类。在这种情况下,您可以为您的程序设置不同的环境,并使用您需要的任何额外模拟/测试数据来设置注入器。一旦您开始执行诸如发出操作请求之类的操作,您就完全超出了单元测试领域。你在这里做的是集成测试 只要您正在进行集成测试,就可以使用
TestServer
,这实际上会为您提供一个更准确的集成测试平台。手动设置所有依赖项并不能确保应用程序真正按其应该的方式运行。完整的文档是,但基本上,您只需执行以下操作:
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_client = _server.CreateClient();
\u server=newtestserver(new WebHostBuilder()
.UseStartup());
_client=_server.CreateClient();
\u server.CreateClient()
的返回实际上是HttpClient
的一个实例,因此您的实际测试代码实际上不需要更改。然而,现在您已经拥有了所有服务和配置的完整模型。一旦您开始执行诸如向操作发出请求之类的操作,您就完全脱离了单元测试领域。你在这里做的是集成测试
只要您正在进行集成测试,就可以使用TestServer
,这实际上会为您提供一个更准确的集成测试平台。手动设置所有依赖项并不能确保应用程序真正按其应该的方式运行。完整的文档是,但基本上,您只需执行以下操作:
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_client = _server.CreateClient();
\u server=newtestserver(new WebHostBuilder()
.UseStartup());
_client=_server.CreateClient();
\u server.CreateClient()
的返回实际上是HttpClient
的一个实例,因此您的实际测试代码实际上不需要更改。但是,现在您已经获得了所有服务和配置的完整模型。我的问题的解决方案如下:
- 创建一个从启动类继承的额外启动类
- 为该类提供以下代码:
public class UnitTestStartup : Startup { public static IServiceProvider ServiceProvider; public static IServiceCollection Services; public static Mock<IConstants> ConstantsMock; public void ConfigureTestingServices(IServiceCollection services) { ServiceProvider = base.ConfigureServices(services); Services = services; ConstantsMock = new Mock<IConstants>(); services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object)); } }
public类UnitTestStartup:Startup { 公共静态IServiceProvider服务提供商; 公共收集服务; 公共静态Mock-ConstantsMock; public void ConfigureTestingServices(IServiceCollection服务) { ServiceProvider=base.ConfigureServices(服务); 服务=服务; ConstantsMock=新Mock(); Replace(新的ServiceDescriptor(typeof(IConstants),ConstantsMock.Object)); } }
- 使ConstantsMock(您想要模拟的服务)在基类中可用
像这样:
protected Mock<IConstants> __constantsMock; __constantsMock = UnitTestStartup.ConstantsMock;
protectedmock\uuu constantsMock; __constantsMock=UnitTestStartup.constantsMock;
- 让每个单元测试类都从基类继承
- 用一个新对象覆盖
,就完成了\uu constantsMock
- 创建一个从启动类继承的额外启动类
- 为该类提供以下代码:
public class UnitTestStartup : Startup { public static IServiceProvider ServiceProvider; public static IServiceCollection Services; public static Mock<IConstants> ConstantsMock; public void ConfigureTestingServices(IServiceCollection services) { ServiceProvider = base.ConfigureServices(services); Services = services; ConstantsMock = new Mock<IConstants>(); services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object)); } }
公共类UnitTestStar
- 我的问题的解决方案如下: