Reputation: 1286
I was writing an unit test for my application. For now I am using Theory with ClassData to create a data-driven unit test. I was wondering is ClassData able to accept parameters so that I can alter the test data based on the input from the test?
Here are some sample code:
This is my data class:
public class InvalidMessageFrame : TheoryData<string, string, string>
{
public InvalidMessageFrame(string messageType)
{
var testData = ReadFromJson(handlerType);
foreach (var data in testData ?? Enumerable.Empty<InvalidMessageTestModel>())
{
Add(data.description, data.message, data.exception);
}
}
private IEnumerable<InvalidMessageTestModel> ReadFromJson(string messageType)
{
var messageObjectName = messageType switch
{
"A" => "Group A",
"B" => "Group B",
"C" => "Group C",
"D" => "Group D",
_ => throw new ArgumentOutOfRangeException(nameof(messageType), messageType, null)
};
var filePath = Path.Combine(Environment.CurrentDirectory, "../../../TestData/InvalidTestData.json");
var json = File.ReadAllText(filePath);
var jObject = JObject.Parse(json);
var testData = jObject[messageObjectName]?.ToObject<IEnumerable<InvalidMessageTestModel>>();
return testData;
}
}
Here is my test:
[Theory]
[ClassData(typeof(InvalidMessageFrame("A")))]
public void InvalidTest(string description, string message, string exception)
{
}
As you can see I was trying to let the Class Data accepts an argument so that I can change the test data based on Group ABCD because in my test data json file each of this group is a list of test data. However it seems impossible with my setup because the error shows in the test for this line [ClassData(typeof(InvalidMessageFrame("A")))]
and the error are: ) expected
.
So if this is not working, I was wondering is there any other method that can achieve the same outcome?
Thank you.
Upvotes: 1
Views: 3150
Reputation: 95
You can not pass parameters to ClassData, but for MemberData it is possible. For you i think @muhmuhhum s answer fits the best, but for others who need to pass parameters this might be helpful.
You have to change the class that provides the data for the test case to something like this:
public class InvalidMessageFrame{
private static IEnumerable<InvalidMessageTestModel> ReadFromJson(string messageType)
{
var messageObjectName = messageType switch
{
"A" => "Group A",
"B" => "Group B",
"C" => "Group C",
"D" => "Group D",
_ => throw new ArgumentOutOfRangeException(nameof(messageType), messageType, null)
};
var filePath = Path.Combine(Environment.CurrentDirectory, "../../../TestData/InvalidTestData.json");
var json = File.ReadAllText(filePath);
var jObject = JObject.Parse(json);
var testData = jObject[messageObjectName]?.ToObject<IEnumerable<object[]>>();
return testData;
}
}
I don't know how you json file looks, maybe you have to adjust the object generation a little.
And your test case to something like this:
[Theory]
[MemberData(nameof(InvalidMessageFrame.ReadFromJson), parameters: "A", MemberType = typeof(InvalidMessageFrame))]
public void InvalidTest(string description, string message, string exception)
{
}
Upvotes: 0
Reputation: 122
With typeof you are only getting the typeof the class not calling the Constructor so you can only write
[ClassData(typeof(InvalidMessageFrame))]
And you can build something like this https://andrewlock.net/creating-a-custom-xunit-theory-test-dataattribute-to-load-data-from-json-files/
Upvotes: 3