【问题标题】:Instantiating IOptions<> in xunit在 xunit 中实例化 IOptions<>
【发布时间】:2018-08-04 07:51:28
【问题描述】:

我正在尝试为一个类(在 .net Core 项目中)编写一个 xunit 测试,看起来像:

public Class FoodStore:IFoodStore
{
    FoodList foodItems;

    public FoodStore(IOptions<FoodList> foodItems)
    {
        this.foodItems = foodItems;
    }

    public bool IsFoodItemPresentInList(string foodItemId)
    {
        //Logic to search from Food List
    }
}`

注意:FoodList 实际上是一个 json 文件,包含数据,在 Startup 类中加载和配置。

如何编写带有适当依赖注入的 xunit 测试来测试 IsFoodItemPresentInList 方法?

【问题讨论】:

  • AutoFixture 很好地自动完成了测试的排列阶段[不能 100% 确定它是否支持您正在使用的特定版本的 .NET Core]。 @metalheart 是正确的,xunit 本身不会做这种事情 - 虽然 v2 确实允许使用共享固定装置进行测试集合,但以您建议的方式滥用它与惯用用法相去甚远

标签: dependency-injection asp.net-core xunit xunit.net asp.net-core-1.0


【解决方案1】:

您可以使用OptionsWrapper&lt;T&gt; 类来伪造您的配置。然后您可以将此对象传递给您要测试的类。这样您就不必使用 DI 或读取真实配置。

类似这样的:

var myConfiguration = new OptionsWrapper<MyConfiguration>(new MyConfiguration
            {
                SomeConfig = "SomeValue"
            });
var yourClass = new YourClass(myConfiguration);

【讨论】:

    【解决方案2】:

    您可以使用Options.Create 方法创建IOptions&lt;FoodList&gt; 的实例:

    var foodListOptions = Options.Create(new FoodList());
    

    【讨论】:

      【解决方案3】:

      我遇到了类似的问题(使用xUnit),经过一番努力,我解决了。

      答案太晚了,但应该对其他人有所帮助。


      对于您的问题:

      public Class FoodStoreTest
      {
          private readonly IConfigurationRoot _configuration;
          private readonly IServiceProvider _serviceProvider;
      
          public FoodStoreTest(){
                  // read Json
                  var configBuilder = new ConfigurationBuilder()
                      .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                      .AddEnvironmentVariables();
                  _configuration = configBuilder.Build();
      
                  // SetUp DI
                  var services = new ServiceCollection();
                  services.AddOptions(); // this statement is required if you wanna use IOption Pattern.
      
                  services.Configure<YuntongxunOptions>(_configuration.GetSection("yuntongxun"));
                  _serviceProvider = services.BuildServiceProvider();
          }
      
          [Fact]
          public void GetFootItemOption()
          {
               IOption<FoodList> optionAccessor = _serviceProvider.GetService<IOptions<FoodList>>();
               FoodList footListOptions = optionAccessor.value;
               Assert.NotNull(footListOptions)
              // ...
          }
      }
      

      另外,您应该将“appSettings.json”复制到您的项目根文件夹。

      【讨论】:

      【解决方案4】:

      在单元测试中,您通常不使用依赖注入,因为是您控制测试对象的创建。

      要提供实现IOptions&lt;FoodList&gt; 的合适对象,您可以自己实现具有所需行为的假类,或使用一些模拟框架动态配置实例,例如Moq

      【讨论】:

      【解决方案5】:

      正如其他答案所建议的,在您的测试类中,您可以创建一个仅用于测试的选项实例。

      你可以这样做;

      public class FakeFoodList : IOptions<FoodList>
      {
          public FoodList Value
          {
              get
              {
                  return new FoodList(); // TODO: Add your settings for test here.
              }
          }
      }
      

      然后这样称呼它;

      var foodOptions = new FakeFoodList();
      var foodStore = new FoodStore(foodOptions);
      
      var response = foodStore.Act();
      
      Assert.Equal("whatever", response);
      

      【讨论】:

        猜你喜欢
        • 2019-06-18
        • 2015-10-30
        • 1970-01-01
        • 1970-01-01
        • 2021-08-08
        • 2019-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多