假设我们要做牛排。
Public class Restaurant{
public void MakeSteak(Steak rawSteak) {
this.KitchenServices.AddSeasoning(rawSteak);
this.KitchenServices.Grill(rawSteak);
}
}
在单元测试中,我可以确保给定一个生牛排,然后将其调味并烧烤:
public void MakeSteakTest() {
var rawSteak = new Steak();
this.restaurant.MakeSteak(rawSteak);
this.KitchenServices.Verify(x => x.AddSeasoning(rawSteak) , Times.Once);
this.KitchenServices.Verify(x => x.Grill(rawSteak) , Times.Once);
}
我的问题是,我们应该进行测试以确保牛排在烧烤后没有调味吗?如果是,怎么办?
答案 0 :(得分:3)
通常,您应该在单元测试中测试结果,而不是实现。如果更改MakeSteak
,以使操作按照不同的顺序进行,系统中会发生什么?那是可观察的东西吗?由于您唯一的意图是Steak
对象,如果在Grill
之前调用AddSeasoning
,是否有某种验证会失败? 那是您应该测试的。
答案 1 :(得分:1)
一种方法是将每个操作表示为对牛排进行操作的命令对象,例如。
interface ISteakOp {
void DoTo(Steak s);
}
class AddSeasoningOp : ISteakOp { ... }
class GrillOp : ISteakOp { ... }
然后返回一系列操作:
public List<ISteakOp> MakeSteakOps() {
return new List<ISteakOp> {
new AddSeasoningOp(),
new GrillOp()
};
}
然后您的测试可以断言在进行任何调味之前都会发生任何烧烤操作:
var ops = MakeSteakOps();
var grillIndex = ops.IndexOf(o => o is GrillOp);
if (grillIndex != -1) {
var seasonIndex = ops.IndexOf(o = o is AddSeasoningOp);
Assert.That(seasonIndex == -1 || seasonIndex < grillIndex);
}
答案 2 :(得分:0)
我的问题是,我们应该进行测试以确保牛排在烧烤后没有调味吗?
首先:它对最终用户/利益相关者可见的行为有影响吗?
如果是,怎么办?
然后:
这听起来可能太“简单” /“过于简单”,但是我非常认真。那就是正确的行为测试的定义。