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?
In addition to the already posted answers. The test cases can be simplified by directly yielding the lambdas.
public class ConfigTestDataProvider
{
public static IEnumerable<object[]> TestCases
{
get
{
yield return new object [] { (Func<Config, object>)((x) => x.Param1) };
yield return new object [] { (Func<Config, object>)((x) => x.Param2) };
}
}
}
This test ConfigTestDataProvider
can then directly inject the lambdas.
[Theory]
[MemberData(nameof(ConfigTestCase.TestCases), MemberType = typeof(ConfigTestCase))]
public void Test(Func<Config, object> func)
{
var config = serviceProvider.GetService<GenericConfig>();
var result = func(config.Config1);
Assert.True(!string.IsNullOrEmpty(result));
}
Actually, I was able to find a solution which is a bit better than the one provided by Iqon (thank you!).
Apparently, the InlineData
attribute only supports primitive data types. If you need more complex types, you can use the MemberData
attribute to feed the unit test with data from a custom data provider.
Here's how I solved the problem:
public class ConfigTestCase
{
public static readonly IReadOnlyDictionary<string, Func<Config, string>> testCases = new Dictionary<string, Func<Config, string>>
{
{ nameof(Config.Param1), (Config x) => x.Param1 },
{ nameof(Config.Param2), (Config x) => x.Param2 }
}
.ToImmutableDictionary();
public static IEnumerable<object[]> TestCases
{
get
{
var items = new List<object[]>();
foreach (var item in testCases)
items.Add(new object[] { item.Key });
return items;
}
}
}
And here's the test method:
[Theory]
[MemberData(nameof(ConfigTestCase.TestCases), MemberType = typeof(ConfigTestCase))]
public void Test(string currentField)
{
var func = ConfigTestCase.testCases.FirstOrDefault(x => x.Key == currentField).Value;
var config = serviceProvider.GetService<GenericConfig>();
var result = func(config.Config1);
Assert.True(!string.IsNullOrEmpty(result));
}
I could maybe come up with something a bit better or cleaner, but for now it works and the code is not duplicated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With