与昨天的question相关。我实施了solution提出的Mehrdad Afshari,但这又引发了另一个问题。
回顾一下:我有一个包含Type->IList<Type>
字典的类,例如Cat->{cat1, cat2}, Zebra->{zebra1, zebra2}
其中Cat
和Zebra
是Animal
的子类。现在Mehrdad提出了以下方法来检索某种类型的所有动物:
IList<T> GetAnimalsOfType<T>() where T : Animal {
return dictionary[typeof(T)].OfType<T>().ToList();
}
这可行,但打破了我的单元测试。原因是Animal是一个抽象类,因此我使用Rhino Mocks来存根(使用animal = MockRepository.GenerateStub<Animal>();
)。我对这个类的单元测试试图创建一个新的动物,然后看它是否包含在字典中。
zoo.AddAnimal(animal);
IList<Animal> animals= zoo.GetAnimalsOfType<Animal>();
Assert.That(animals[0], Is.EqualTo(animal));
不幸的是Rhino Mocks创造的动物类型是一个动物代理,我要求动物,这打破了我的考验。关于如何纠正这种情况的任何建议?
更新:感谢所有解决方案。
答案 0 :(得分:2)
您可以询问刚刚插入的特定类型。你必须创建一个辅助函数:
T Get<T>(T parameterOnlyToInferTheType)
{
IList<Animal> animals= zoo.GetAnimalsOfType<T>();
return animals[0];
}
animal = MockRepository.GenerateStub<Animal>();
zoo.AddAnimal(animal);
Animal expected = Get(animal);
Assert.That(expected, Is.EqualTo(animal));
看起来有点狡猾,但应该工作。
一般情况下,我倾向于避免在类型上键入集合,因此我没有这些问题(例如,我在类上返回枚举的属性等)。
答案 1 :(得分:1)
由于编译器需要事先知道类型,因此您无法使用它:
zoo.AddAnimal(animal);
IList<Animal> animals= zoo.GetAnimalsOfType<typeof(animal)>();
Assert.That(animals[0], Is.EqualTo(animal));
我认为你必须推出自己的模拟:
class MockAnimal : Animal
{
}
zoo.AddAnimal(new MockAnimal());
IList<Animal> animals= zoo.GetAnimalsOfType<MockAnimal>();
Assert.That(animals[0], Is.EqualTo(animal));
您也不想检查返回的实例是否与添加的实例不同,而不仅仅是等于? (不是确定的语法,仍然是Asset.AreSame())
Assert.That(animals[0], Is.SameAs(animal));
其他并不令人惊讶,因为你希望GetAnimalsOfType
只返回确切类型的动物不是你,而不是那些衍生出来的类型?如果你这样做了:
class Tiger : Animal
{
}
zoo.AddAnimal(new Tiger());
IList<Animal> animals= zoo.GetAnimalsOfType<Animal>();
你希望这会通过:
Assert.AreEqual(1, animals.Count);
我假设没有。如果你想做你概述的事情,我想你必须创建一个真正的动物而不是模拟。