Lambda expression as inline data in xUnit

Viewed 5059

I'm pretty new to xUnit and here's what I'd like to achieve:

[Theory]
[InlineData((Config y) => y.Param1)]
[InlineData((Config y) => y.Param2)]
public void HasConfiguration(Func<Config, string> item)
{
    var configuration = serviceProvider.GetService<GenericConfig>();
    var x = item(configuration.Config1); // Config1 is of type Config

    Assert.True(!string.IsNullOrEmpty(x));            
}

Basically, I have a GenericConfig object which contains Config and other kind of configurations, but I need to check that every single parameter is valid. Since they're all string, I wanted to simplify using [InlineData] attribute instead of writing N equals tests.

Unfortunately the error I'm getting is "Cannot convert lambda expression to type 'object[]' because it's not a delegate type", which is pretty much clear.

Do you have any idea on how to overcome this?

5 Answers

I have the problem the same to you, and I found the solution that using TheoryData class and MemberData attribute. Here is the example and I hope the code usefully:

public class FooServiceTest
{
    private IFooService _fooService;
    private Mock<IFooRepository> _fooRepository;

    //dummy data expression
    //first parameter is expression
    //second parameter is expected
    public static TheoryData<Expression<Func<Foo, bool>>, object> dataExpression = new TheoryData<Expression<Func<Foo, bool>>, object>()
    {
        { (p) => p.FooName == "Helios", "Helios" },
        { (p) => p.FooDescription == "Helios" && p.FooId == 1, "Helios" },
        { (p) => p.FooId == 2, "Poseidon" },
    };

    //dummy data source
    public static List<Foo> DataTest = new List<Foo>
    {
        new Foo() { FooId = 1, FooName = "Helios", FooDescription = "Helios Description" },
        new Foo() { FooId = 2, FooName = "Poseidon", FooDescription = "Poseidon Description" },
    };

    //constructor
    public FooServiceTest()
    {
        this._fooRepository = new Mock<IFooRepository>();
        this._fooService = new FooService(this._fooRepository.Object);
    }

    [Theory]
    [MemberData(nameof(dataExpression))]
    public void Find_Test(Expression<Func<Foo, bool>> expression, object expected)
    {
        this._fooRepository.Setup(setup => setup.FindAsync(It.IsAny<Expression<Func<Foo, bool>>>()))
                               .ReturnsAsync(DataTest.Where(expression.Compile()));

        var actual = this._fooService.FindAsync(expression).Result;
        Assert.Equal(expected, actual.FooName);
    }
}
public class HrcpDbTests
{    
    [Theory]
    [MemberData(nameof(TestData))]
    public void Test(Expression<Func<bool>> exp)
    {
        // Arrange
        // Act
        // Assert
    }
    
    public static IEnumerable<object[]> TestData 
    {
        get
        {
            Expression<Func<bool>> mockExp1 = () => 1 == 0;
            Expression<Func<bool>> mockExp2 = () => 1 != 2;

            return new List<object[]>
            {
                new object[]
                {
                    mockExp1
                },
                new object[]
                {
                    mockExp2
                }
            }
        }
    }
}
Related