Skip to content

xUnit Attributes

Overview

  • xUnit provides various attributes to define and control the behavior of test methods.
  • The most commonly used attributes are [Fact] and [Theory].

Fact Attribute

  • The [Fact] attribute is used to denote a test method that takes no parameters.
  • It is a simple test case that is always true.
[Fact]
public void TestAdd()
{
    //Arrange
    var a = 1;
    var b = 2;

    //Act
    var result = MathUtil.Add(a, b);

    //Assert
    Assert.Equal(3, result);
}

Theory Attribute

  • The [Theory] attribute is used for parameterized tests.
  • It allows you to run the same test method with different sets of data.
  • You can provide data using attributes like [InlineData], [MemberData], or [ClassData].

InlineData Attribute

  • The [InlineData] attribute allows you to specify the data directly in the attribute.
    [Theory]
    [InlineData(5, 3, 2)]
    [InlineData(10, 4, 6)]
    [InlineData(0, 0, 0)]
    public void TestSubtract(int a, int b, int expected)
    {
        //Act
        var result = MathUtil.Subtract(a, b);
        //Assert
        Assert.Equal(expected, result);
    }
    

MemberData Attribute

  • The [MemberData] attribute allows you to specify a property or method that returns the data for the test.
  • This is useful for more complex data sets.

 [Theory]
 [MemberData(nameof(GetDistanceTestData))]
 public void TestDistanceTo_WithMemberData(Point2D pointA, Point2D pointB, double expectedDistance)
 {
     //Act
     var distance = pointA.DistanceTo(pointB);
     //Assert
     Assert.Equal(expectedDistance, distance, 5);
 }

 public static IEnumerable<object[]> GetDistanceTestData()
 {
     yield return new object[] { new Point2D(0, 0), new Point2D(3, 4), 5.0 };
     yield return new object[] { new Point2D(1, 1), new Point2D(4, 5), 5.0 };
     yield return new object[] { new Point2D(-1, -1), new Point2D(2, 3), 5.0 };
 }
- For class with multiple test methods, you can organize the MemberData like this:

  public class Point2DTest
  {
      [Theory]
      [MemberData(nameof(TestDataPoint2D.Distance), MemberType = typeof(TestDataPoint2D))]
      public void TestDistanceTo_WithMemberData(Point2D pointA, Point2D pointB, double expectedDistance)
      {
          //Act
          var distance = pointA.DistanceTo(pointB);
          //Assert
          Assert.Equal(expectedDistance, distance, 3);
      }
  }
  public static class TestDataPoint2D
  {
      public static IEnumerable<object[]> Distance()
      {
          yield return new object[] { new Point2D(0, 0), new Point2D(10, 0), 10 };
          yield return new object[] { new Point2D(0, 0), new Point2D(10, 10), 14.1421 };
          yield return new object[] { new Point2D(1, 2), new Point2D(3, 4), 2.8284 };
      }
  }

ClassData Attribute

  • The [ClassData] attribute allows you to specify a class that implements IEnumerable <object[]> to provide the data for the test.
public class Point2DTest
{
    [Theory]
    [ClassData(typeof(DistanceTestData))]
    public void TestDistanceTo_WithMemberData(Point2D pointA, Point2D pointB, double expectedDistance)
    {
        //Act
        var distance = pointA.DistanceTo(pointB);
        //Assert
        Assert.Equal(expectedDistance, distance, 3);
    }
}

public class DistanceTestData : IEnumerable<object[]>
{
    public IEnumerator<object[]> GetEnumerator()
    {
        yield return new object[] { new Point2D(0, 0), new Point2D(3, 4), 5.0 };
        yield return new object[] { new Point2D(1, 1), new Point2D(4, 5), 5.0 };
        yield return new object[] { new Point2D(-1, -1), new Point2D(2, 3), 5.0 };
    }

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}