Reputation: 470
My test method looks like this:
public static List<Something> Generator() {
return A.GenerateObjects();
}
[Test, TestCaseSource(nameof(Generator))]
public void DoSomething(Something abc) {/*do something*/}
This code works very well and generates for each object in the list an unit case.
I want to include another parameter in the method like:
public void DoSomething(Something abc, string def)
I've tried it with these lines but it didn't work:
public static object[] Case =
{
new object[]
{
A.GenerateObjects(),
someStrings
}
};
Maybe iterate the list with an loop function instead of invoking the method (GenerateObjects()) directly? I also don't understand how Nunit can recognize the objects from the list directly with only TestCaseSource(nameof(Generator))
Thanks in advance!
Upvotes: 4
Views: 4894
Reputation: 13736
Your initial test takes a single argument of type Something
. Apparently, A.GenerateObjects()
returns some sort of IEnumerable of those objects - you don't show the detail. Because the test is a single-argument method, that works. NUnit provides a special case for single argument methods, which is very forgiving and will accept arrays of objects or of the type that is required and generate the test cases for you itself.
However, for multiple arguments, it's up to you to return a set of test cases from your method yourself. As you probably know, the arguments to a method in C# are in the form of an object[]
containing the arguments, like new object[] { aSomething, "astring" }
.
Assuming that you have specific strings that need to be associated with each object, it's up to you to make that association. How to do that depends on the details of what you are trying to do.
Do you have a list of strings, which you want to associate with the list of objects one for one? In that case, stop using [TestCaseSource]
and use [ValueSource]
or [Values]
on each parameter of the test method. Apply [Sequential]
to the method to cause NUnit to match up the objects and strings one for one. Here's an example...
[Test, Sequential]
public void DoSomething(
[ValueSource(typeof(A), nameof(GetObjects)] Something abc,
[Values("string1", "string2", "string3")] string def)
{/*do something*/}
This is just one way to do it. I've had to do a bunch of guessing as to what data you have readily available and what you are trying to do. If this approach doesn't work for you, please fill in the blanks a bit and I'll edit the answer.
Upvotes: 0
Reputation: 1333
You can return an IEnumerable of TestCaseData like this:
public static IEnumerable<TestCaseData> Generator()
{
yield return new TestCaseData(new Something { SomeValue = "Hi" }, "Foo").SetName("FirstTest");
yield return new TestCaseData(new Something { SomeValue = "Bye" }, "Bar").SetName("SecondTest");
}
[Test]
[TestCaseSource(nameof(Generator))]
public void DoSomething(Something abc, string def)
{
Console.WriteLine($"{abc.SomeValue},{def}");
}
The SetName is optional, just if you want a more meaningful name than the default one it makes up.
I also don't understand how Nunit can recognize the objects from the list directly with only TestCaseSource(nameof(Generator))
Nunit notices the TestCaseSource attribute on the test method, and then uses reflection to invoke the "Generator" method. (Nameof is just sugar, the compiler substitutes it with the actual name when you build it). Every TestCaseData object that is returned is another test case. In my example above the tests will be run twice. FirstTest will have a Something instance where SomeValue is set to Hi and a def string of Foo. SecondTest will have a Something instance where SomeValue is set to Bye and a def string of Bar.
Upvotes: 6