0

我是 TDD 的新手。我是第一次这样做。少有困惑。看看下面的 MVC 示例:

CarApiController:GetCar、GetCars、PostCar、PutCar、DeleteCar

CarBLL(静态类):GetCar、GetCars、PostCar、PutCar、DeleteCar

CarDAL(静态类):SelectCar、SelectCars、InsertCar、UpdateCar、DeleteCar

为了在 CarApiController 中使用 GetCars 获取汽车列表,调用堆栈将是: CarApiController.GetCars() -> CarBLL.GetCars() -> CarDAL.SelectCars()

我应该只为 CarApiController 编写测试吗?还是我应该为所有三层都写?如果我为所有三层编写,CarDAL 将总共测试 3 次,一次用于它自己的测试,然后当我测试 CarBLL 和 CarApiController 时。同样,CarBLL 将对其自己的测试进行一次测试,并在我测试 CarApiController 时再次进行测试。

这应该怎么做?

4

3 回答 3

4

如果你想采用 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

很抱歉答案很长,但这是一个非常复杂和广泛的主题......祝你好运,编码愉快!:)

于 2013-07-08T09:47:16.337 回答
0

是的,您测试所有层。你独立地测试它们。

您需要研究 TDD 的概念。在 TDD 中,您测试所有内容,并在编写生产代码之前和期间编写测试。

你需要学习的另一件事是嘲笑。当您测试一个类时,您使用模拟/存根(有些人称之为假货)作为输入,而不是使用您在生产代码中使用的真实类。当你测试时CarApiController,所有的输入都应该被模拟,所以你单独测试这个类。通过这种方式,您可以测试一个类,并且只测试一个类。

于 2013-07-08T09:48:17.137 回答
-1

最好只覆盖 CarBLL。

当然,您可以覆盖所有层。但是,您应该尝试保持控制器薄而 BLL 胖。如果您发现您的控制器变得越来越大,您应该考虑将该逻辑移至 BLL。

我想说所有的 BLL 类都应该包含单元测试。用单元测试覆盖所有层总是好的,因为这将在重构代码时为您提供帮助,但是我已经看到了一些情况,即编写的单元测试只是测试框架和这样的测试只是浪费时间......

想要注意的是,从您在问题中说明的架构示例中,如果您查看“通用控制器”和“通用存储库模式”会很好。

这是通用控制器示例的链接,代码并不完美,但它为您提供了一些提示,如何根据您的需要构建通用控制器。

这是一篇关于为什么不应该测试控制器的好文章:http: //www.codeproject.com/Articles/607396/Youplusshouldplusunitplustestplusyourpluscontrolle

于 2013-07-08T09:46:19.887 回答