【问题标题】:Populating complex objects from an Excel sheet and passing it as a parameter to a [Theory]从 Excel 工作表填充复杂对象并将其作为参数传递给 [Theory]
【发布时间】:2014-06-04 12:58:20
【问题描述】:

我使用 mstest 编写了以下测试,我有一个 Excel 表,上面有大约 20 行,每行测试运行一次,TestContext 的 DataRow 属性填充了该行的数据。将 TestContext 对象传递给 PopulateCustomerViaDataSource 方法,以便使用 Excel 工作表中的客户详细信息填充客户对象,然后将客户对象传递给 Web 方法,以便将详细信息导入另一个应用程序。因此,基本上特定测试运行的所有数据都可以使用一个对象访问,即 TestContext,它甚至不必传递给测试,因此填充 Customer 对象非常容易。

[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);
}

现在我的问题是如何使用 xUnit 获得与此类似的结果。我已经尝试了一段时间,但没有做对,我一直在谷歌搜索,但找不到专门证明这一点的文章/帖子。我能找到的所有关于 xUnit 上的数据驱动的文章都会导致参数被单独传递,如下所示。

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(); }
}

如果我的测试只有 1 或 2 个参数,那很好,但其中一些有 20 多个参数,需要填充客户对象和其他对象,所以我想避免将 20 多个参数传递到方法中,如上面的例子,要么让一些类似 TestContext 的对象或另一个填充了数据的对象,我可以用它来填充 Customer 对象,或者传入一个已经填充了特定测试行的数据的 Customer 对象。

上述任何一种方法都是可能的,还是有另一种方法可以在避免传递这么多参数的同时做到这一点?如果不是,你们会以不同的方式做这个测试吗?如果是的话,怎么做?

我将不胜感激任何指导/建议。

【问题讨论】:

    标签: c# unit-testing mstest xunit.net data-driven-tests


    【解决方案1】:

    最近又看了一遍,搞明白了。当我第一次尝试这样做时,我是 xUnit 的新手,不知道/不明白我需要使用列表类型提供测试数据。

    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...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-01
      • 2011-09-06
      • 1970-01-01
      • 2012-04-22
      • 2019-08-12
      • 1970-01-01
      相关资源
      最近更新 更多