Question

I wrote the below test using mstest, I've got an Excel sheet with about 20 lines on it, test runs once for each line and the TestContext's DataRow property is populated with the data for that line. The TestContext object is passed to the PopulateCustomerViaDataSource method for the customer object to be populated with the customer details from the Excel sheet, and the customer object is then passed to a web method for the details to be imported into another application. So basically all the data for the specific test run is accessible using one object, i.e. TestContext, which doesn't even have to be passed to the test, so populating Customer objects for example are easy as pie.

[DataSource("System.Data.Odbc", "Dsn=Excel Files;Driver={Microsoft Excel Driver (*.xls)};dbq=|DataDirectory|\\Data.xls;defaultdir=.;driverid=790;maxbuffersize=2048;pagetimeout=5;readonly=true", "ApVendorImportCreate$", DataAccessMethod.Sequential), TestMethod]
public void CustomerImport_CreateVendor()
{
    Customer customer = CustomerImportHelpers.PopulateCustomerViaDataSource(TestContext);
    Result result;

    using (SomeWebService client = new SomeWebService())
    {
        result = client.CustomerImport(customer);
    }

    Assert.IsTrue(result.Success, "Customer import was unsuccessful.  Returned error message was \"" + result.Message + "\"");
    AssertCustomerInfoSavedCorrectly(customer);
}

Now my question is how do I achieve a result similar to this using xUnit. I've been trying for a while now but not getting it right and I've been googling but not able to find an article / post that demonstrates this specifically. All the articles I could find about data driven stuffies on xUnit result in the parameters being passed in individually like below.

public class StringTests3
{
    [Theory, ClassData(typeof(IndexOfData))]
    public void IndexOf(string input, char letter, int expected)
    {
        var actual = input.IndexOf(letter);
        Assert.Equal(expected, actual);
    }
}

public class IndexOfData : IEnumerable<object[]>
{
    private readonly List<object[]> _data = new List<object[]>
    {
        new object[] { "hello world", 'w', 6 },
        new object[] { "goodnight moon", 'w', -1 }
    };

    public IEnumerator<object[]> GetEnumerator()
    { return _data.GetEnumerator(); }

    IEnumerator IEnumerable.GetEnumerator()
    { return GetEnumerator(); }
}

If my tests only had 1 or 2 params it would be fine but some of them have 20+ parameters with which Customer objects and others need to be populated, so I want to avoid passing 20+ params into the method like in the above example by either having some TestContext-like or another object populated with the data, which I can use to populate the Customer objects, or passing in a Customer object already populated with the data for the specific tests' line.

Is any of the above possible or is there another way of doing this while avoiding passing in so many params? If not, would you guys do this test differently and if so how?

I would greatly appreciate any guidance / advice.

Was it helpful?

Solution

Had a look at this again recently and figured it out. Back when I tried to do it the first time I was new to xUnit and didn't know / understand that I needed to provide the test data using a list type.

public class TestDataFixture
{
    public static IEnumerable<object[]> TestData
    {
        get
        {
            var testCases = new List<object[]>();

            var testCase = new object[1];

            var testData1 = new TestDataClass()
            {
                name = "Piet",
                surname = "Pompoies"
            };

            testCase[0] = testData1;

            testCases.Add(testCase);

            return testCases;
        }
    }
}

public class DieMatrixReloaded
{
    [Theory]
    [MemberData("TestData", MemberType = typeof(TestDataFixture))]
    public void DieMatrixReloadedTheory(TestDataClass testData)
    {
        var someVar = testData;
        //Assert something here...
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top