Stub protected基类中的List用于单元测试

时间:2013-08-07 15:30:53

标签: c# unit-testing nunit moq

我想测试一个方法是否将对象添加到基类中的列表。

我的问题是该列表受到保护,因此我无法在我的测试安排中填充它。因此列表为空,我的方法无法在特定索引处添加对象。

如何创建存根列表并使用它而不是真正的基类列表而不公开它?

我正在使用NUnit和Moq。

以下是一些模仿我问题的代码:

public class Person
{
    public string Name { get; set; }
    readonly List<PhoneNumber> _numbers = new List<PhoneNumber>();

    public void AddNumber(PhoneNumber phoneNumber)
    {
        _numbers.Add(phoneNumber);
    }
}

public class PhoneNumber
{
    public int Number { get; set; }
}

public class BaseClass
{
    protected List<Person> Persons = new List<Person>();
}

public class DerivedClass : BaseClass
{
    public void AddNumberToPersons(int index, PhoneNumber phoneNumber)
    {
        Persons[index].AddNumber(phoneNumber); // <-- Need to test if 
                                               // this gets called without errors
    }
}

[Test]
public void AddNumberToPersons_WhenAddingNumberToPersons_NumberGetsAddedToList()
{
    // I think I need to use a stub list or else the list is empty 
    // and index is out of range.

    // Assert that number is added to the list.
}

1 个答案:

答案 0 :(得分:0)

在评论中有一些很好的讨论,为什么你可能想要考虑一下你正在尝试测试什么。也就是说,在某些情况下,您可能希望设置类以使用其基类进行测试。在这种情况下,我倾向于使用手动滚动的可测试版本。因此,在您的测试项目中,如果您可以像这样创建DerivedClass的可测试版本:

public class TestableDerived : DerivedClass {
    public TestableDerived(List<Person> people) {
        this.Persons = people;
    }
    public List<Person> AccessablePersons { get { return this.Persons; } }
}

TestableDerived类可以访问层次结构中的protected成员,因此您可以在测试的排列部分填充它。通常,您可以验证相应Person的状态是否已更新以添加该数字。这可能会给你一个像这样的测试:

var sut = new TestableDerived(new List<Person>(){new Person(), new Person()});

sut.AddNumberToPersons(1, new PhoneNumber { Number = 1234 });

Assert.AreEqual(1, sut.AccessablePersons[1].Numbers.Where(x=>x.Number == 1234).Count());

在您的特定示例中,这不会起作用,因为您的Person类在添加后无法访问PhoneNumbers。有一些方法可以解决这个问题,但这似乎不是您问题的焦点,所以我选择相信这是您的示例代码中的遗漏并添加了Numbers存取器。