如果你想采用 TDD 方式并且你真的想确保代码的可测试性,你必须摆脱你的static
类。另一点是,如果您要进行 TDD,您应该开始编写测试并让设计出现,而在这里您已经对您希望您的设计如何......
正如您自己指出的那样,DAL 将以这种方式测试 3 次,但这还不是最糟糕的部分。最糟糕的是,您无法单独测试 ApiController 或 BLL,这意味着如果测试中出现问题,您将不知道哪个类失败了,这违背了单元测试的目的:快速查明失败的原因。
我会做的是这样的:
ICarDAL (interface) -> SelectCar, SelectCars, InsertCar, UpdateCar, DeleteCar
CarDAL 将实现上述接口。
ICarBLL (interface) -> GetCar, GetCars, PostCar, PutCar, DeleteCar
让我们忽略 BLL 反映 Api 方法的事实。在我的想法中,BLL 应该提供独立于使用层的逻辑,因此可能有以下方法:GetCars、AddCar、EditCar、CreateCar ...例如,PostCar 和 PutCar 变得毫无意义。
CarBLL 实现了上述功能。由于 CalBLL 使用 DAL,它的构造函数看起来像这样:
public CarBLL(ICarDAL dal)
{
this.dal = dal;
}
对于控制器:
CarApiController -> GetCar, GetCars, PostCar, PutCar, DeleteCar
CarApiController 将有一个类似的构造函数:
public CarApiController(ICarBLL bll)
{
this.bll = bll;
}
调用堆栈保持不变,但现在您的代码已解耦。请注意,要在 ApiController 中使用参数化构造函数,您需要在应用程序中注册某种 IoC 容器。过去我非常满意地使用过Unity 。
现在我们可以跳舞了。我们的测试将如下所示:
控制器测试:
public void test_that_this_works()
{
ICarBLL mock = new FakeCarBLL();
var controller = new CarApiController(mock);
Assert.That(controller.GetCars.Count(), Is.EqualTo(1));
}
有了上面的内容,你可以编写一个 BLL 接口的假实现,它总是返回相同的结果,你可以检查控制器中的操作是否执行正常。BLL 测试看起来很相似,但您将使用 DAL 的假实现来模拟来自数据库的一组结果,并可能验证 Save 和 Select 方法被调用的次数正确(在这种情况下,我建议使用模拟库,例如RhinoMocks)
很抱歉答案很长,但这是一个非常复杂和广泛的主题......祝你好运,编码愉快!:)