我有一个类,我想在其一个公共方法中实现单元测试,以测试是否调用了特定方法。
为了简化它,我们来看下面的课程和单元测试。
我应该更改或实现什么(如界面等),以便我可以断言“MakeNoise方法调用Bark方法”
如果需要,我可以使用RhinoMocks。
public class Animal
{
public string AnimalType {get; set;}
public string Bark()
{
if(AnimalType=="dog")
{
return "Hof! Hof! Hof!";
}
return string.Empty;
}
public string MakeNoise()
{
if(AnimalType=="dog")
{
return Bark();
}
return
string.Empty;
}
}
[TestMethod]
public void MakeNoise_WithAnimalTypeDog_CallsBarkMethod()
{
var dog = new Animal(){AnimalType="dog"};
dog.MakeNoise();
// How can I test if the MakeNoise method called BarkMethod ?
}
答案 0 :(得分:3)
这是你感兴趣的,输出。测试输出。
var expected = "Hof! Hof! Hof!";
var actual = dog.MakeNoise();
Assert.AreEqual(actual, expected);
如果方法在被测试的类中,那么它是一个实现细节。您可能希望测试互动的位置,如果您的班级有合作者,并且您希望将Animal
的测试与协作者(可能是Bar
)隔离开来。 然后您可以选择使用假Bar
来确保Animal
行为正确(当然,您已经为做了适当的测试真实的 Bar
)。如果这更接近您的真实问题,请更新它。
话虽如此,你的类层次结构(如果这确实是一个指示)可以使用一些工作。 Animal
不应该只有一种与狗有关的方法。你不应该在类中进行类型检查(class,enum,whatever)。创建一个继承自Dog
的{{1}},让它适当地覆盖Animal
方法。
MakeNoise
你甚至可以使class Animal
{
public virtual string MakeNoise() { return whatever; }
}
class Dog : Animal
{
public override string MakeNoise() { return "Hof! Hof! Hof!"; }
}
//
Animal dog = new Dog();
var noise = dog.MakeNoise();
抽象。
答案 1 :(得分:1)
您永远不应该检查某个方法是否调用另一个方法。实际的实现永远不应该是有趣的。
imho适当的单元测试应该是“黑匣子”测试。你不应该知道方法包含什么样的逻辑。你应该只知道它提供的那种结果以及它可以抛出什么样的异常(以及在什么条件下)。那些指定的案例是你应该测试的案例。答案 2 :(得分:1)
虽然我同意@jgauffin一个单元测试实际上不应该那样,但是无论如何都有一种脏的方法。
首先,定义您的Bark方法虚拟。然后,在继承类中覆盖它,该类是测试套件的一部分。
public class AnimalTestClass : Animal
{
public bool BarkCalled{get;set;}
public override string Bark()
{
BarkCalled = true;
return base.Bark();
}
}
然后,在您的测试方法中,实例化此类
[TestMethod]
public void MakeNoise_WithAnimalTypeDog_CallsBarkMethod()
{
var dog = new AnimalTestClass(){AnimalType="dog"};
dog.MakeNoise();
// How can I test if the MakeNoise method called BarkMethod ?
Assert.IsTrue(dog.BarkCalled);
}
编辑:修正了代码拼写错误(忘记调用base.Bark())