繁体   English   中英

使用ASP.NET Core 2.0集成测试HttpClient如何通过依赖项注入模拟DateTime.Now

[英]Integration test HttpClient using ASP.NET Core 2.0 How to mock DateTime.Now with dependency injection

我已经在.net Core 2.0框架中使用依赖项注入和httpClient编写了一些单元测试。 我一直在测试我的控制器,如下所示:

var result = await  __client.PostAsync("api/production-line/validate-assignment-deadline", null);

但是现在我想模拟一个对象,在互联网上搜索了一下之后,我所能找到的就是这样做:

var controller = new ProductionLineController(mockProductionLineProvider);

这没有测试路由,最重要的是我必须创建很多对象。 所以我不想以此方式嘲笑我的对象。 我希望能够用模拟对象替换服务,但我还没有找到一种将IServiceCollection放入我的unittest方法的方法。

我希望能够做这样的事情:

    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.Now的结果,所以现在我使常量类具有一个返回datetime.now的函数,我正在尝试模拟/对类/函数进行存根。 这样,我可以测试可能发生的多种情况。

您正在寻找模拟的标准方式; 您为所有依赖项创建存根(您需要能够控制所有依赖项!)并创建控制器。 能够模拟DI框架并不会真正给您带来任何好处。 在构造类时,您仍然需要向该类提供所有依赖项。

使用诸如NSubstitute之类的模拟库可以使其变得更容易; 如果您觉得自己的依赖关系太多,那么我会怀疑您需要重构设计(也许控制器做得太多)。

请注意,使用实际的HTTP请求进行测试更多是一种集成测试。 您正在测试整个应用程序,而不仅仅是一个类。 在这种情况下,您可以为程序设置不同的环境,并拥有一个可以根据需要的额外模拟/测试数据来设置注射器的环境。

一旦开始执行诸如向动作发出请求之类的事情,您就远远超出了单元测试范围。 您在这里所做的是集成测试。

只要您正在执行集成测试,就可以使用TestServer ,它实际上将为您提供一个更准确的集成测试平台。 手动设置所有依赖项并不能确保您的应用程序能够正常运行。 完整的文档在这里 ,但是基本上,您只需要:

_server = new TestServer(new WebHostBuilder()
    .UseStartup<Startup>());
_client = _server.CreateClient();

_server.CreateClient()的返回实际上是HttpClient一个实例,因此您实际的测试代码实际上不需要更改。 但是,现在您已经拥有了所有服务和配置的完整模型。

解决我的问题的方法如下:

  • 制作一个从StartUp类继承的额外入门类
  • 给该类以下代码:

     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)); } } 
  • 使ConstantsMock(您要模拟的服务)在您的基类中可用,如下所示:

     protected Mock<IConstants> __constantsMock; __constantsMock = UnitTestStartup.ConstantsMock; 
  • 让每个单元测试类都从您的基类继承

  • 用新对象覆盖__constantsMock ,您就完成了

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM