Difference between Fact and Theory? - xUnit.net

sternze picture sternze · Mar 13, 2014 · Viewed 47.1k times · Source

I'm new to xUnit.net and AutoFixture.

I'm currently working on a "testproject" to get familiar with xUnit.net and Autofixture. There is one little thing I don't understand.

What is the difference between [Fact] and [Theory, AutoMoqData]?

Could you please tell me if the following two pieces of code are equal? I'm asking this because the Test succeeds with both, but I want to learn it the right way.

[Fact]
public void UpdateVersionWillUpdateCorrectlyInRepository()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    var contract = fixture.Create<VersionContract>();
    var version = fixture.Create<Version>();

    fixture.Freeze<Mock<IContractMapper>>()
        .Setup(r => r.Map(contract)).Returns(version);

    var repMock = fixture.Freeze<Mock<VersionRepository>>();

    var sut = fixture.Create<VersionManagementService>();

    sut.UpdateVersion(contract);

    repMock.Verify(r => r.UpdateVersion(version));
}

and

[Theory, AutoMoqData]
public void UpdateVersionWillUpdateCorrectlyInRepository(
    VersionContract contract,
    Version version,
    [Frozen]Mock<IContractMapper> mapMock,
    [Frozen]Mock<VersionRepository> repMock,
    VersionManagementService sut)
{
    mapMock.Setup(r => r.Map(contract)).Returns(version);

    sut.UpdateVersion(contract);

    repMock.Verify(r => r.UpdateVersion(version));
}

What makes me think that there is a difference are the Keywords [Fact] and [Theory].

I'm assuming that the [Theory] Keywords tells the xUnit.net framework that the supplied data comes from somewhere, where somewhere is Autofixture. Whereas [Fact] tells xUnit nothing about the origin of the data and I need to build the objects manually.

Answer

Mark Seemann picture Mark Seemann · Mar 13, 2014

Assuming that your [AutoMoqData] attribute looks something like this:

public class AutoMoqDataAttribute : AutoDataAttribute
{
    internal AutoMoqDataAttribute()
        : base(new Fixture().Customize(new AutoMoqCustomization()))
    {
    }
}

Then, yes, those two tests are equivalent.

Both [Fact] and [Theory] attributes are defined by xUnit.net.

The [Fact] attribute is used by the xUnit.net test runner to identify a 'normal' unit test: a test method that takes no method arguments.

The [Theory] attribute, on the other, expects one or more DataAttribute instances to supply the values for a Parameterized Test's method arguments.

xUnit.net itself supplies various attributes that derive from DataAttribute: [InlineData], [ClassData], [PropertyData].

AutoFixture hooks into this extensibility point of xUnit.net by supplying the [AutoData] attribute. It can be used to make tests more declarative.