C# 使用假货';在同一对象中的另一个方法上调用
使用FakeiTasy,我如何检查我的对象的方法是否调用了同一对象上的另一个方法 测试:C# 使用假货';在同一对象中的另一个方法上调用,c#,unit-testing,fakeiteasy,C#,Unit Testing,Fakeiteasy,使用FakeiTasy,我如何检查我的对象的方法是否调用了同一对象上的另一个方法 测试: [TestMethod] public void EatBanana_CallsWillEat() { var banana = new Banana(); var myMonkey = new Monkey(); myMonkey.EatBanana(banana); //this throws an ArgumentException, because myMonkey is a r
[TestMethod]
public void EatBanana_CallsWillEat()
{
var banana = new Banana();
var myMonkey = new Monkey();
myMonkey.EatBanana(banana);
//this throws an ArgumentException, because myMonkey is a real instance, not a fake
A.CallTo(() => myMonkey.WillEat(banana)
.MustHaveHappened();
}
班级:
public class MyMonkey {
private readonly IMonkeyRepo _monkeyRepo;
public MyMonkey(IMonkeyRepo monkeyRepo) {
_monkeyRepo = monkeyRepo;
}
public void EatBanana(Banana banana) {
//make sure the monkey will eat the banana
if (!this.WillEat(banana)) {
return;
}
//do things here
}
public bool WillEat(Banana banana) {
return !banana.IsRotten;
}
}
我愿意接受建议。如果我在这件事上做错了,请告诉我。这样做是可能的。如果将eat
方法是虚拟的,否则FakeiTesy将无法伪造它
通过这一更改,您可以执行以下操作:
[TestMethod]
public void EatBanana_CallsWillEat()
{
var fakeMonkey = A.Fake<MyMonkey>();
fakeMonkey.EatBanana(new Banana());
A.CallTo(()=>fakeMonkey.WillEat(A<Banana>._)).MustHaveHappened();
}
[TestMethod]
公共电话号码()
{
var fakeMonkey=A.Fake();
fakeMonkey.eatbana(新香蕉());
A.CallTo(()=>fakeMonkey.WillEat(A.);
}
我仍然不相信这是一个好主意(正如我在评论中咆哮的那样)——我认为你最好依靠其他可观察到的行为,但我不熟悉你的系统。如果您认为这是最好的方法,那么示例代码应该适合您。为什么要模拟测试对象?你到底想测试什么?对
的调用将执行的验证没有什么价值。it向消费者提供哪些信息?毕竟,消费者并不关心方法是如何实现的。消费者关心结果是什么
当猴子吃了香蕉而香蕉并没有腐烂时会发生什么?您的测试应回答以下问题:
[TestMethod]
public void EatBanana_CAUSES_WHAT_WhenBananaIsNotRotten()
{
var repo = A.Fake<IMonkeyRepo>();
var monkey = new Monkey(repo);
var freshBanana = new Banana { IsRotten = false };
monkey.EatBanana(freshBanana);
// verifications here depend on what you expect from
// monkey eating fresh banana
}
[TestMethod]
公共利益导致了什么
{
var repo=A.Fake();
风险值猴子=新猴子(回购);
var freshBanana=newbanana{IsRotten=false};
猴子。吃香蕉(新鲜香蕉);
//这里的验证取决于您期望从中得到什么
//猴子吃新鲜香蕉
}
请注意,您可以对IMonkeyRepo
进行各种验证,这是正确伪造并在此处注入的。据我所知,这并不是FIE的真正目的。FIE提供了假对象,因此您的生产代码可以更容易地戳和戳。正如你所指出的,你没有假的。根据我的经验,这种测试通常不是一个好主意。您的MyMonkey类应该是一个相当独立的单元,您最好在被命令吃香蕉时测试它的整体行为,而不是担心它是否调用了自己的方法。例如,你能根据“/”中发生的事情判断香蕉是否被吃掉吗?@BlairConrad在我的真实场景中,WillEat更复杂,有自己的测试,这只是EatBanana的测试之一。在这个测试中,如果我让EatBanana调用真正的WillEat,我不是在一个测试中测试两个特性吗?然后,如果WillEat改变,它可能会打破这个测试,这是个坏消息,对吗?我明白你的意思。这很棘手。如果要吃另一个对象,我们都会敦促伪造该对象并将其注入MyMonkey
(听起来很痛苦)。我真正能说的是,我认为最好的默认位置是尝试从外部测试MyMonkey
,依靠客户的可观察结果。但是,您已经考虑过了,并且已经找到了一个解决方案,它将节省您的痛苦,减少测试的数量以及在给定时间内中断的数量。你最了解代码,所以如果它对你有用的话……我只是想让你知道另一种选择。很好。如果我不模仿WillEat,并且允许EatBanana调用真正的WillEat,那么我是否在一个测试中测试了两个特性?在本例中,WillEat很简单,但在我的实际情况中,它更复杂,并且根据它的参数返回一个派生对象,因此我认为模拟它并验证它是否被调用是正确的方法。目前,我对WillEat进行了单独的测试,对EatBanana进行了一些其他测试,包括验证是否调用了回购协议。也许我变得太细了?@JoshNoe:也许你变得不够细了。如果会吃
那么复杂,也许它应该生活在自己的类中?也许将这一特性提取到食物评估器之类的东西中,并将其注射到猴子身上更有意义?测试应该是简单的——如果不是,通常是一个很好的指标,表明设计可以重新进行。另一方面,为什么Monkey
依赖于IMonkeyRepository
?