Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiating IOptions<> in xunit

I'm trying to write an xunit test for a class (in a .net Core project) that looks something like:

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
    }
}`

Note: FoodList is actually a json file, containing data, that is loaded and configured in the Startup class.

How can I write an xunit test with appropriate dependency injection to test the IsFoodItemPresentInList method ?

like image 893
Michael McDowell Avatar asked Mar 08 '16 11:03

Michael McDowell


4 Answers

I have encountered a similar problem (using xUnit), after some struggle, I worked it out.

The answer is so late, but should be helpful for others.


For your Question:

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)
        // ...
    }
}

Also, you should copy "appSettings.json" to your project root folder.

like image 77
MienDev Avatar answered Nov 08 '22 00:11

MienDev


You can create an instance of IOptions<FoodList> using the Options.Create method:

var foodListOptions = Options.Create(new FoodList());
like image 31
mikesigs Avatar answered Nov 07 '22 23:11

mikesigs


You could use OptionsWrapper<T> class to fake your configuration. Then you can pass in this object to your class that you want to test. That way you don't have to use DI or read the real configuration.

Something like this:

var myConfiguration = new OptionsWrapper<MyConfiguration>(new MyConfiguration
            {
                SomeConfig = "SomeValue"
            });
var yourClass = new YourClass(myConfiguration);
like image 35
Đorđe Petrović Avatar answered Nov 07 '22 23:11

Đorđe Petrović


In a unit test, you typically don't use Dependency Injection, since it's you who controls the creation of the tested object.

To supply a suitable object that implements IOptions<FoodList> you can implement a fake class with the desired behavior yourself, or use some mocking framework to configure the instance on the fly, for example Moq.

like image 41
metalheart Avatar answered Nov 07 '22 22:11

metalheart