简体   繁体   English

适应单元测试的方法。 这似乎是错误的

[英]Methods adapted to satisfy unit tests. This just seems wrong

I have begun to dabble in unit testing, and have created a couple of tests that test one of my presenter methods. 我开始涉足单元测试,并创建了一些测试我的演示者方法之一的测试。 This testing requires a mock of my data access class, and one method in particular. 此测试需要模拟我的数据访问类,尤其是一个方法。 This is the original method from my data access class: 这是我的数据访问类中的原始方法:

public IEnumerable<IArea> GetAreaList()
    {
        ConnectToTFSProject();

        XmlNode areaNode = GetAreaNode();
        List<IArea> areaList = new List<IArea>();

        foreach (XmlNode node in areaNode.FirstChild.ChildNodes)
        {
            IArea area = new Area() { AreaName = node.Attributes["Name"].Value };
            areaList.Add(area);
        }

        areaList.Sort();

        return areaList;
    }

I would like to test the presenter method with different scenarios, eg: 我想在不同的情况下测试Presenter方法,例如:

  • a regular list of areas 常规区域清单
  • an empty list of areas 空区域列表
  • a list of areas with duplicates 重复区域列表
  • a list or areas containing one empty string area 包含一个空字符串区域的列表或区域

My first thought was to create a separate mock data access class for each of these scenarios. 我的第一个想法是为每种情况创建一个单独的模拟数据访问类。 I thought this to be a little cumbersome, so I adapted the method slightly to allow the reading of different xml files, containing data specific to the current test. 我认为这有点麻烦,因此我稍微修改了该方法,以允许读取不同的xml文件,其中包含特定于当前测试的数据。 Here is how my mock method looks: 这是我的模拟方法的外观:

public IEnumerable<IArea> GetAreaList(string dataSource)
    {
        List<IArea> areaList = new List<IArea>();

        XmlTextReader areaReader = new XmlTextReader(dataSource);

        while (areaReader.Read())
        {
            if (areaReader.NodeType == XmlNodeType.Text)
                areaList.Add(new Area() { AreaName = areaReader.Value });
        }

        return areaList;
    }

This mock method will then be called from the PresenterTest class as follows: 然后,将从PresenterTest类中调用此模拟方法,如下所示:

[TestMethod]
    public void PopulateAreaComboBox_WithValidAreaList()
    {
        //Act
        _presenter.PopulateAreaComboBox(mockFolderPath + "MockAreaList.xml");

        //Assert
        Assert.AreEqual(3, _view.AreaListLoaded.Count);
    }

    [TestMethod]
    public void PopulateAreaComboBox_WithEmptyAreaList()
    {
        //Act
        _presenter.PopulateAreaComboBox(mockFolderPath + "MockEmptyAreaList.xml");

        //Assert
        Assert.AreEqual(0, _view.AreaListLoaded.Count);
    }

Now, the problem I have here is that I now need to change the signature of my original method (by adding reference to the dataSource parameter): 现在,这里的问题是我现在需要更改原始方法的签名(通过添加对dataSource参数的引用):

public IEnumerable<IArea> GetAreaList(string dataSource)

Because this parameter is required only for the unit tests, the value of null is passed into this method from the real presenter class, and never used. 因为只有单元测试才需要此参数,所以null的值将从真正的presenter类传递到此方法中,并且从不使用。

I know this is wrong but how should this be accomplished? 我知道这是错误的,但是应该如何实现呢? Should I create a separate mock data access class that sets up each test data scenario? 我是否应该创建一个单独的模拟数据访问类来设置每个测试数据方案?

I resolved this by exposing a public string (TestDataXml) in my mock data access class. 我通过在模拟数据访问类中公开一个公共字符串(TestDataXml)来解决此问题。 I then created a new instance of the mock data access class for each test, setting this string to the location of an individual test data xml file each time: 然后,我为每个测试创建了模拟数据访问类的新实例,每次都将此字符串设置为单个测试数据xml文件的位置:

class MockDataRetrieval : IDataRetrieval
{
    public string TestDataXml { get; set; }

    public IEnumerable<IArea> GetAreaList()
    {
        List<IArea> areaList = new List<IArea>();

        XmlTextReader areaReader = new XmlTextReader(TestDataXml);

        while (areaReader.Read())
        {
            if (areaReader.NodeType == XmlNodeType.Text)
                areaList.Add(new Area() { AreaName = areaReader.Value });
        }

        return areaList;
    }
}

To call the mock method from the PresenterTest class: 要从PresenterTest类调用模拟方法:

    [TestMethod]
    public void PopulateAreaComboBox_WithValidAreaList()
    {
        //Arrange
        _data = new MockDataRetrieval() { TestDataXml = mockFolderPath + "MockAreaList.xml" };
        _view = new MockMainForm();

        _presenter = new TestCasePresenter(_view, _data);

        //Act
        _presenter.PopulateAreaComboBox();

        //Assert
        Assert.AreEqual(3, _view.AreaListLoaded.Count);
    }

    [TestMethod]
    public void PopulateAreaComboBox_WithEmptyAreaList()
    {
        //Arrange
        _data = new MockDataRetrieval() { TestDataXml = mockFolderPath + "MockEmptyAreaList.xml" };
        _view = new MockMainForm();

        _presenter = new TestCasePresenter(_view, _data);

        //Act
        _presenter.PopulateAreaComboBox();

        //Assert
        Assert.AreEqual(0, _view.AreaListLoaded.Count);
    }

Ralf: Thanks for your comment. 拉尔夫:谢谢你的评论。 This question relates to testing the Presenter.PopulateAreaComboBox method. 此问题与测试Presenter.PopulateAreaComboBox方法有关。 The GetAreaList method in this example is from the mock data access class, and simply provides the method under test with test data. 本示例中的GetAreaList方法来自模拟数据访问类,并且仅向测试中的方法提供测试数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM