gpt4 book ai didi

asp.net-mvc - TDD'ing MVC Controller 驱动设计

转载 作者:行者123 更新时间:2023-12-04 16:02:44 25 4
gpt4 key购买 nike

我正在开始一个新项目(嗯,重新启动现有项目),并尝试采用 TDD(第 n 次)以获得它应该带来的所有好处。

我相信 TDD 将导致我的测试驱使我只编写我需要编写的代码,但它会驱使我编写我需要的代码而不遗漏一些代码。

这就是我目前的不确定状态出现的地方。

考虑这个故事:

“用户必须能够添加小部件,这样他们才能查看新添加的小部件的详细信息。”

好的,所以从 UI 开始工作(因为用户将从那里添加他们的小部件,而不是使用 Visual Studio 和我编写的一组程序集)......我从以下测试开始,编写非常少的内容,以便测试通过。

所以我从 Controller 开始抛出一个 NotImplementedException,然后返回一个 View()... 以下是我写的最少的行以使测试通过的第一点。

[TestFixture]
public class WidgetControllerTester
{

[Test]
public void Create_IfBusinessModelIsValid_ReturnRedirectToRouteResultToDetailsAction()
{
// Arrange
var currentUser = new User
{
DisplayName = "Fred",
Email = "fred@widgets.com",
Password = "pass",
Status = UserStatus.Active
};
var model = new WidgetModel();
var controller = new WidgetController();
// Act
var actionResult = controller.Create(currentUser, model);
// Assert
actionResult.AssertActionRedirect().ToAction("Details");
}
}

public class WidgetModel
{
}

public class WidgetController: Controller
{
public ActionResult Create()
{
return View("Create");
}

[HttpPost]
public ActionResult Create(User currentUser, Widget model)
{
return RedirectToAction("Details");
}
}

现在我意识到对无效模型的额外测试和模型状态检查将从额外的故事演变而来。

但是,我看不到如何利用其他测试在 Controller 中驱动更多代码的清晰路径。

例如,我知道在某个时候我会想从 Create 操作中调用 WidgetService。我是否遗漏了一些明显的东西(看不到树木的树木之类的东西)我如何通过额外的测试来推进 Controller 代码?

谈到 WidgetService,我希望我会编写一个 WidgetServiceTester,而此时 Controller 中的引用很可能会被 mock 。

我曾经的一些想法...
  • 创建一个名为 Create_IfModelIsValid_WidgetIsAddedToRepository 的新测试,但这如何清楚地导致 Controller 操作中的服务调用?
  • 我需要写一个更详细的故事,说明模型需要插入存储库/数据库等?
  • 我混淆了 TDD 和 XP 的元素吗?

  • 感谢您的阅读,我将不胜感激任何关于进步的最佳实践的反馈和见解。

    乔。

    编辑 2010 年 2 月 27 日

    我找到了以下文章迭代 #6 – 使用测试驱动开发(在 asp.net 上)( http://www.asp.net/%28S%28ywiyuluxr3qb2dfva1z5lgeg%29%29/learn/mvc/tutorial-31-cs.aspx),它演示了我所追求的那种东西,但是他们似乎认为将存储库/服务添加到 Controller 作为重新-factoring ...我个人不同意,我错了吗? :)

    我将考虑编写一个测试来检查 Details 操作的 ViewData 并在我有后更新这个问题。

    最佳答案

    乔。有时,我也有很多同样的不确定性。但我也认为你所缺少的大部分是那些前期的故事。首先,您应该稍微分解您的故事以创建实际的开发人员需求。这就是我的意思:

    "A user must be able to add a widget, doing so they are taken to view the details of the newly added widget."



    好的,对我来说,问题如下,可以帮助你思考测试:

    “用户”——用户从何而来?他们是如何登录的? (如果您使用默认的 AccountController 和测试,那么它已经存在,如果没有,您将需要测试以获取登录表单、登录、验证成功和失败的登录等)

    “添加小部件” - 什么(我不是指实现,我只是指出这意味着您将要访问存储库或服务,除非“添加”只是意味着将其添加到运行中实例,你不需要持久性)?此时小部件是否必须有效,或者可以保存无效的小部件并在以后使其有效?这对我来说意味着测试存储库或服务是否有方法命中(save()、insert()、add() 等等(不是方法的内部,直到你开始测试你的服务/repo,只是 Controller 通过调用它来完成它的工作),检查在有效/无效小部件上发生了什么(您需要稍微扩展您的故事或添加一个故事以涵盖在有效/无效小部件上应该发生的事情)

    “这样做,他们会查看新添加的小部件的详细信息”——稍微改写了一下,但基本上就是你所说的。总是?还是只有成功?此 View 是可编辑的还是只读的(即编辑操作或详细信息操作)?是否有消息告诉用户他们已经成功,或者他们应该从他们正在查看他们的小部件这一事实中推断出他们是成功的?这应该驱动测试,例如检查返回的操作结果的属性并检查存储在 TempData(状态消息)中的值以及检查两个路径中发生的情况(成功或失败)。

    这只是一个快速的镜头,但基本上这就是思考过程。您也可以对其他故事执行相同的操作,并为此生成新故事以涵盖更多应用程序行为。

    关于你的设计的一些想法。

    您的下一个测试应该首先查看我上面写的内容,即 Controller 的创建 POST 操作应该 1)接收所需的数据(您的参数),2)调用该服务/存储库以“添加”小部件,3)可能如果添加失败,请做一些事情(这是你的设计;我已经到了我的 Controller 假设一切顺利的地方,我通过属性处理失败,但那是个人设计决定),4)重定向到细节。

    因此,您的下一个测试将使用模拟(我更喜欢 google 代码上的 moq 库,但无论您拥有什么都可以)。您将需要一些接口(interface)来描述您的 Controller 将调用的服务,并将该服务的模拟实现传递给正在测试的 Controller ,以确保它调用正确的方法。在最小起订量中,这看起来像这样:
    [Test] 
    public void Create_CallsRepository()
    {
    // Arrange
    var currentUser = new User
    {
    DisplayName = "Fred",
    Email = "fred@widgets.com",
    Password = "pass",
    Status = UserStatus.Active
    };
    var model = new WidgetModel();
    var mockService = new Mock<IService<WidgetModel>();
    mockService.Setup(s=>s.Add(model)); //.Returns(whatever) if it returns something
    var controller = new WidgetController(mockService.Object);

    // Act
    var actionResult = controller.Create(currentUser, model);

    // Assert
    mockService.Verify(s=>s.Add(model));
    }

    当然,这会产生一些设计假设,但是如何编写测试与如何调用/处理对象之间的紧张关系是 TDD 如此有值(value)的部分原因。

    关于asp.net-mvc - TDD'ing MVC Controller 驱动设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2345578/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com