我正在开发一个 Spring MVC 项目,并且对源树中的所有各种组件进行了单元测试。

例如,如果我有一个控制器 HomeController, ,这需要有一个 LoginService 注入其中,然后在我的单元测试中 HomeControllerTest 我只是像平常一样实例化对象(在 Spring 之外)并注入属性:

protected void setUp() throws Exception {
    super.setUp();
    //...
    controller = new HomeController();
    controller.setLoginService( new SimpleLoginService() );
    //...
}

这对于将每个组件作为一个独立的单元进行测试非常有用 - 除了现在我的项目中有几十个类,在编写一个类并为其编写成功的单元测试之后,我总是忘记更新我的 Spring MVC 上下文文件已部署应用程序中的实际接线。当我将项目部署到 Tomcat 并从未连线的 bean 中找到一堆 NullPointers 时,我发现我忘记更新上下文文件。

所以,这是我的问题:

  1. 这是我的第一个 Spring 项目 - 正如我所做的那样,为各个 bean 创建单元测试,然后创建第二套测试(集成测试)来测试一切是否按实际应用程序上下文的预期工作,这是否正常?对此是否有既定的最佳实践?

  2. 另外,如何将单元测试与集成测试分开?我有所有的源代码 src, ,单元测试在 test - 是否应该有第二个测试文件夹(例如 test-integration)用于集成测试用例?

由于这是我的第一个 Spring 项目,我很好奇其他人通常是如何做这类事情的——与其重新发明轮子,我宁愿询问社区的其他人。

有帮助吗?

解决方案

我不能说这是最佳实践,但这就是我过去所做的。

单元测试:

  • 为重要的 bean(即大多数与 Spring 相关的 bean)创建单元测试
  • 在可行的情况下(即,大多数情况下,如果不是一直),使用模拟来注入服务。
  • 对项目中的这些测试使用标准命名约定 test 目录。使用 Test 或者 TestCase 作为类名的前缀或后缀似乎被广泛采用。

集成测试:

  • 创建一个 AbstractIntegrationTestCase 这设立了一个 Spring WebApplicationContext 用于集成测试类。
  • 在集成测试中使用命名约定 test 目录。我用过 IntTest 或者 IntegrationTest 作为这些测试的前缀或后缀。

设置三个Ant test 目标:

  1. 测试全部(或者任何你想命名的名称):运行单元和集成测试
  2. 测试:运行单元测试(只是因为 test 似乎是单元测试最常见的用法
  3. 测试集成:运行集成测试。

如前所述,您可以使用对您的项目有意义的命名约定。

至于将单元与集成测试分离到一个单独的目录中,我认为只要开发人员 和他们的工具 可以轻松找到并执行它们。

举个例子,我使用 Spring 开发的最后一个 Java 项目完全使用了上面描述的内容,集成测试和单元测试位于同一个容器中。 test 目录。另一方面,Grails 项目在通用测试目录下明确分隔单元测试目录和集成测试目录。

其他提示

一些孤立的观点:

是的,这是Spring测试的常用方法 - 单独的单元测试和集成测试,前者不加载任何Spring上下文。

对于您的单元测试,可以考虑进行模拟以确保您的测试集中在一个隔离模块上。

如果你的测试是依赖大量的依赖,那么它们就不是真正的单元测试。它们是集成测试,您可以使用new而不是依赖注入来连接依赖项。当您的生产应用程序使用Spring时浪费时间和重复工作!

用于调出Spring上下文的基本集成测试非常有用。

@required注释可以帮助您确保在Spring连线中捕获所需的依赖项。

也许看看Maven会给你明确的阶段来绑定你的单位和集成测试。 Maven在Spring社区中得到了广泛的应用。

如果你也转换到一个纯粹注释的制度,你可以用@ Component,@ Controller,@ Service和@Repository注释你所有的bean,那么很多繁琐的春季双书保存就会消失。只需将@Autowired添加到您需要注入的属性中。

参见弹簧参考手册的3.11节。 http://static.springframework。组织/弹簧/文档/ 2.5.X /参考/ beans.html#豆-注释的配置

在相关的说明中,我们一直在使用KenG描述的Unit / Integratrion分区测试。在我最近的政权中,我们还引入了第三个“阶级”。测试,“ComponentTests”。它们采用全弹簧布线,但采用有线短线实现(使用弹簧中的元件扫描滤波器和注释)。

我们这样做的原因是因为对于某些“服务”而言。你最终会得到一大堆手工编码的布线逻辑来手动连接bean,有时还会有大量的模拟对象。用于5行测试的100条线路并不罕见。组件测试缓解了这个问题。

使用InitializingBean接口(实现方法“afterPropertiesSet”)或为bean指定init方法。 InitializingBean通常更容易,因为您不需要记住将init方法添加到bean中。

使用afterPropertiesSet确保所有内容都注入为非null,如果为null,则抛出异常。

当我为Web应用程序创建集成测试时,我将它们放在一个单独的目录中。它们是使用jUnit或TestNG构建的,并使用 Selenium 等网页与被测系统进行交互。好像他们是用户。循环将如下所示:编译,运行单元测试,构建Web应用程序,将其部署到正在运行的服务器,执行测试,取消部署应用程序以及报告结果。这个想法是测试整个系统。

关于与集成测试分开运行单元测试,我将所有后者放入集成测试目录并使用IDE / Ant使用类似。适合我。

单元测试和集成测试之间的区别在于,单元测试不一定加载你的上下文,你专注于你编写的代码 - 它通过模拟任何依赖调用快速失败,即有和没有例外在里面。 但是在集成测试的情况下,您可以加载上下文并像实际场景一样执行端到端测试。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top