如何处理私有成员访问者和集合?

时间:2010-02-01 17:35:26

标签: c# visual-studio-2008 unit-testing private-members generic-interface

我有一个类似这样的课程

public class A
{
    protected class B 
    {
        String Name { get; set; }
    }

    protected class C : KeyedCollection<String, B> 
    {
        // ...
    }

    protected C Collection { get; }

    // ...

    public A Copy () 
    {
        // Creates a deep copy of this instance.
    }
}

现在我想写一个单元测试来比较A的两个实例是否在KeyedCollection属性中具有相同的项目B.但是,我无法在A实例中执行foreach循环。我曾尝试过,

[TestClass]
public class TestClass
{
    public void ATest()
    {
        A original = new A();
        A copy = A.Copy();

        // ...

        A_Accessor originalAccessor = A_Accessor.AttachShadow(original);
        A_Accessor copyAccessor = A_Accessor.AttachShadow(copy);

        foreach(var originalItem in originalAccessor.Collection)
        {
            var copyItem = copyAccessor[originalItem.Name];
            Assert.AreEqual(originalItem, copyItem);
        }
    }
}

这段代码甚至没有编译,因为C类访问器没有实现IEnumerable接口(它没有实现KeyedCollection类的任何接口)。有没有人知道如何克服这个问题呢?

我收到的错误消息是

foreach语句不能对“C”类型的变量进行操作,因为“A_Accessor.C”不包含“GetEnumerator”的公共定义

4 个答案:

答案 0 :(得分:0)

目前尚不清楚如何通过受保护的属性开始公开私有类类型,但由于C 派生自 KeyedCollection,它应该已经继承了{的实现{1}}。

你要做的事情并不是很清楚,但是你仍然可以迭代这个集合...如果你甚至可以看到这个属性。我怀疑你的代码由于其他原因而无法编译 - 因为IEnumerable<B>是根据私有成员类型声明的,尽管受到保护,并且因为你试图从另一个类中访问C第一名(尽管受到保护)。

答案 1 :(得分:0)

我只是试图编译你的例子:正如预期的那样我得到了一个错误

Inconsistent accessibility: field type 'A.C' is less accessible than field 'A.Collection'

基本上,这意味着您不能使用私有类型声明受保护的属性。所以这不是你的测试代码的问题,而是要测试的代码......

编辑

您可以使用originalAccessor.Collection.Target并将其投放到ICollection。当然,在这种情况下,您只能枚举object秒,因此您必须再次投射每个项目:

foreach (var item in (originalAccessor.Collection.Target as ICollection)) {
   A_Accessor.B casted = A_Accessor.B.AttachShadow(item);
   var copyItem = copyAccessor[casted.Name];
   Assert.AreEqual(casted, copyItem);
}

答案 2 :(得分:0)

实际上,我发现的解决方案与Martin的建议非常相似:

var originalItems = 
    from item in (originalAccessor.Collection.Target as IEnumerable).Cast<Object>()
    select A_Accessor.B.AttachShadow(item);

var copyItems = 
    from item in (copyAccessor.Collection.Target as IEnumerable).Cast<Object>()
    select A_Accessor.B.AttachShadow(item); 

foreach(var original in originalItems) 
{ 
    String originalName = original.Name;
    A_Accessor.B copy = copyItems.First(b => b.Name == originalName);

    // ...
}

感谢您的帮助! 卡洛斯。

答案 3 :(得分:0)

在我看来,您正在测试实现细节,而不是库的用户的预期API级别。