3

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!

B0r1
  • 400
  • 3
  • 15
  • You should create a new `object` for every instance returned by `A.GenerateObjects`, unless you want to have only a single test that works on an array of `Something`. – MakePeaceGreatAgain May 04 '18 at 12:21

2 Answers2

5

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.

Adam G
  • 1,283
  • 1
  • 6
  • 15
0

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.

Charlie
  • 12,928
  • 1
  • 27
  • 31
  • Hi Charlie, thanks for your reply. What do you mean with GetObjects (GenerateObjects?) What I forgot to mention is that the string parameter is only a particular value (an url). I'll try your solution but at the moment I don't have the time to validate it. I will get back to you. – B0r1 May 07 '18 at 11:17