加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 我只是不了解TDD单元测试(Asp.Net MVC项目)?

发布时间:2020-12-16 00:25:18 所属栏目:asp.Net 来源:网络整理
导读:我试图找出如何正确和有效地单元测试我的Asp.net MVC项目。当我开始这个项目时,我买了Pro ASP.Net MVC,并且和我一起学习了TDD和单元测试。在看到这些例子之后,以及我在现任公司担任质量保证工作的软件工程师的事实,我很惊讶于TDD似乎是多么的棒极了。所
我试图找出如何正确和有效地单元测试我的Asp.net MVC项目。当我开始这个项目时,我买了Pro ASP.Net MVC,并且和我一起学习了TDD和单元测试。在看到这些例子之后,以及我在现任公司担任质量保证工作的软件工程师的事实,我很惊讶于TDD似乎是多么的棒极了。所以我开始研究我的项目,并为我的数据库层,业务层和控制器进行了gung ho写入单元测试。一切都在实施之前进行了单元测试。起初我以为这是真棒,但事情开始下坡了。

以下是我开始遇到的问题:

>我最终编写了应用程序代码,以使单元测试成为可能。我的意思不是很好,因为我的代码被破坏,我必须修复它,以便单元测试通过。我的意思是将数据库抽象为模拟数据库是不可能的,因为使用linq进行数据检索(使用通用存储库模式)。

原因是使用linq-> sql或linq->实体,您可以通过执行以下操作来加入:

var objs = select p from _container.Projects select p.Objects;

但是,如果您嘲笑数据库层,为了让该linq通过单元测试,您必须将linq更改为

var objs = select p from _container.Projects
       join o in _container.Objects on o.ProjectId equals p.Id
       select o;

这不仅意味着您正在更改应用程序逻辑,以便您可以对其进行单元测试,但是您仅仅为了实现可测试性而使代码效率降低,并且使用ORM摆脱了很多优势。 。

此外,由于我的模型的很多ID都是数据库生成的,所以我证明必须编写额外的代码来处理非数据库测试,因为ID不会被生成,我还必须处理这些单元测试通过的情况,但它们永远不会发生在真实情况下。

因此,我最终抛出了我的数据库单元测试。
只要我返回观点,写控制器的单元测试就很容易。然而,我的应用程序的主要部分(以及最受益于单元测试的)是一个复杂的ajax Web应用程序。由于各种原因,我决定将应用程序从返回的视图更改为使用我需要的数据返回JSON。发生这种情况之后,我的单元测试变得非常痛苦,因为我没有找到任何好的方法来编写单元测试用于非平凡的json。

在捣毁我的头,浪费了大量的时间,试图找到一个很好的方法来单元测试JSON,我放弃了并删除了我所有的控制器单元测试(所有控制器的操作都集中在这个应用程序的这一部分)。
>所以最后我离开了测试服务层(BLL)。现在我正在使用EF4,但是我也遇到linq-> sql这个问题。我选择了做EF4模型的第一种方式,因为对我来说,这样做是有道理的(定义我的业务对象,让框架弄清楚如何将它转换成sql后端)。这一开始很好,但现在由于关系而变得笨重。

例如说我有Project,User和Object实体。一个对象必须与项目相关联,并且项目必须与用户关联。这不仅仅是一个数据库特定的规则,这些也是我的业务规则。但是,我想做一个单元测试,我可以保存一个对象(一个简单的例子)。我现在必须做以下代码,以确保保存工作:

User usr = new User { Name = "Me" };
_userService.SaveUser(usr);

Project prj = new Project { Name = "Test Project",Owner = usr };
_projectService.SaveProject(prj);

Object obj = new Object { Name = "Test Object" };
_objectService.SaveObject(obj);

// Perform verifications

有许多问题需要做所有这些只是为了执行一个单元测试。这有几个问题。

>对于初学者,如果我添加一个新的依赖项,例如所有的项目都必须属于一个类别,我必须进入每个引用一个项目的单个单元测试,添加代码来保存类别,然后添加代码来添加类别到项目。这可能是一个非常简单的业务逻辑变革的巨大努力,但几乎没有一个单元测试我将修改这个要求实际上是测试该功能/要求。
>如果我然后添加验证到我的SaveProject方法,所以项目不能保存,除非他们有一个至少5个字符的名称,然后我必须通过每个对象和项目单元测试,以确保新的要求不任何不相关的单元测试失败。
>如果UserService.SaveUser()方法中存在问题,它将导致所有项目和对象单元测试失败,并且原因不会立即引起注意,而无需挖掘异常。

因此,我已经从我的项目中删除了所有服务层单元测试。

我可以继续,但到目前为止,我没有看到任何方式进行单元测试来实际帮助我,而不是让我的方式。我可以看到具体的情况,我可以,也可能会实施单元测试,例如确保我的数据验证方法正常工作,但这些情况是很少的。我的一些问题可能会被缓解,但不能在我的应用程序中添加额外的层次,从而使得更多的故障点就可以进行单元测试。

因此,我的代码中没有单元测试。幸运的是,我大量使用源代码管理,所以我可以让他们回来,如果我需要,但我只是没有看到这一点。

互联网上的任何地方,我看到人们谈论TDD单元测试是多么的好,我不只是在讨论狂热的人。解散TDD /单元测试的少数人提供了不利的论据,声称他们通过IDE进行更有效的调试,或者他们的编码技术令人惊奇,他们不需要它。我认识到这两个论点都是完全的公牛,特别是对于需要由多个开发人员维护的项目,但对TDD的任何有效的反驳似乎都是很少的。

所以这个帖子的要点是问,我只是不了解如何使用TDD和自动单元测试?

解决方法

你可以看看我写的 sample ASP.NET MVC 2.0 project structure。它提供了一些可能让您开始对单元测试控制器逻辑和数据库的概念。就数据库测试而言,它不再是单元测试,而是集成测试。正如您将在我的示例中看到的,我使用NHibernate,它允许我轻松地切换到为每个测试夹具重新创建的示例SQLite数据库。

最后在ASP.NET MVC中进行单元测试可能是一个痛苦,没有妥善分离关注和抽象,并使用像MVCContrib.TestHelper这样的嘲笑框架和框架可以使您的生活更轻松。

Here’s a preview您的控制器单元测试可能如何。

更新:

作为对评论的回应,我认为编程是一项具体任务,很难给出如何单元测试我的复杂业务应用程序的最终答案。为了能够测试复杂的应用程序,层之间的耦合应尽可能弱,这可以通过接口和抽象类来实现。我同意,在复杂的应用中实现这样一个薄弱的耦合并不是一件小事。

我可以给你一个建议:如果整个TDD的概念很难理解,你没有看到没有好处,那么这是可以的。没有人可以证明TDD在所有情况下都是有益的。只需尝试设计您的应用程序,使每个课程都有一个责任。如果发现自己在同一个类中验证输入,SQL数据访问和异常处理,那么你做错了。一旦实现了这种分离,您将看到单元测试变得更加容易,甚至可以在单元测试驱动您的开发阶段进行调试:-)

单元测试JsonResult与MvcContrib.TestHelper是一个具体的问题,我给了一个具体的答案:

public class MyModel
{
    public string MyProperty { get; set; }
}

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return Json(new MyModel { MyProperty = "value" });
    }
}

和测试:

[TestMethod]
public void HomeController_Index_Action_Should_Return_Json_Representation_Of_MyModel()
{
    // arrange
    var sut = new HomeController();

    // act
    var actual = sut.Index();

    // assert
    actual
        .AssertResultIs<JsonResult>()
        .Data
        .ShouldBe<MyModel>("")
        .MyProperty
        .ShouldBe("value");
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读