Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the preferred way to handle multiple test cases in Xunit?

I have migrated to using Xunit for unit tests from NUnit. With NUnit, I would create one method with multiple test cases that have the same outcome. For example, the following NUnit unit test tests the validation of a class constructor, specifically the "name" variable. The name can't be null, empty or whitespace. The test checks that an ArgumentNullException is correctly thrown:

    [Test]
    [TestCase(null)]
    [TestCase("")]
    [TestCase("     ")]
    [ExpectedException(typeof(ArgumentNullException))]
    public void Constructor_InvalidName_ExceptionThrown(string name)
    {
        // action
        make_Foo(name);
    }

    private make_Foo(string name)
    {
        return new Foo(name);
    }

This is how I have implemented this using Xunit:

    [Fact]
    public void Constructor_InvalidName_ExceptionThrown()
    {
        Assert.Throws<ArgumentNullException>(() => new Foo(null));
        Assert.Throws<ArgumentNullException>(() => new Foo(""));
        Assert.Throws<ArgumentNullException>(() => new Foo("    "));
    }

This seems bad for two reasons - I have multiple Asserts in what is supposed to be a "unit" test, and with the test cases buried within the method (which could get a lot more complicated in some of the other unit tests).

What is the preferred way to handle multiple test cases in Xunit?

like image 891
08Dc91wk Avatar asked Aug 06 '15 08:08

08Dc91wk


People also ask

Why xUnit is preferred more than NUnit or MSTest?

XUnit vs. MSTest is concerned, the biggest difference between xUnit and the other two test frameworks (NUnit and MSTest) is that xUnit is much more extensible when compared to NUnit and MSTest. The [Fact] attribute is used instead of the [Test] attribute.

How do I run a parallel test in xUnit?

Set to true to run the test assemblies in parallel against one other; set to false to run them sequentially. The default value is false . Set to true to run the test collections in parallel against one other; set to false to run them sequentially. The default value is true .


1 Answers

You can use the Theory attribute to the same effect:

[Theory()]
[InlineData(null)]
[InlineData("")]
[InlineData("     ")]
public void Constructor_InvalidName_ExceptionThrown(string name)
{
    Assert.Throws<ArgumentNullException>(() => new Foo(name));
}

I am not sure if xUnit has am attribute equivalent to ExpectedException however. If there is, I would not use it.

There used to be an ExpectedException attribute in xUnit but it has since been deprecated in favour of Assert.Throws.

like image 92
Alex Booker Avatar answered Oct 27 '22 00:10

Alex Booker