如何使用Java单元测试助手高效构建和改进Spring测试?

Spring框架(连同Spring Boot一块儿)是最流行的Java企业软件框架之一。它在关键任务应用中的使用意味着它的质量和安全性受到了严格的审查。html

此前,咱们讨论了开发人员如何不喜欢单元测试,尽管它的改进记录已被证明,并详细介绍了Parasoft Jtest的单元测试助手如何提供一种指导性和自动化的测试方法,使测试不只更容易接受,并且更容易和更有效。在这篇文章中,我将继续以Spring框架为主题,向你展现如何在这个重要的应用框架中利用自动化和引导式测试。java

测试Spring应用的挑战

Spring框架为集成测试提供了不错的支持,但要正确设置测试用例,须要大量的手工编码。构建和维护Spring应用的测试给开发人员带来了一系列独特的挑战,包括如下几点安全

  • 必须对Spring框架进行初始化和配置
  • 应用程序一般有第三方库的依赖性(持久存储、外部服务等)
  • 应用程序一般使用内置的Spring功能,用于会话、安全、消息传递等。对于刚接触Spring测试的开发人员来讲,这些功能的设置可能会很棘手
  • 须要适当配置应用程序的依赖关系(即Bean

这些挑战,再加上编写全面的可维护的测试套件通常须要花费大量的时间,致使开发人员没有编写足够的测试,反过来,这又会致使安全漏洞、缺陷、回归和许多使人头痛的问题。app

Parasoft Jtest Unit Test Assistant能够帮助你,它使生成、改进和维护JUnit测试的过程变得更加简单和省时,这样开发人员就能够快速构建好的测试,并回到他们更加偏好的事情上——编写代码。框架

Spring MVC测试框架

Spring框架包括一个测试框架,它使控制器、服务和其余组件的测试变得更加容易。它包括配置Spring测试容器、调用Controller处理方法和使用自定义断言验证行为的功能。函数

一个Spring MVC控制器的例子工具

@Controller

public class TodoController {     @Autowired

    private TodoService service;

    @GetMapping("/")    public String findAll(Model model) {

        List<Todo> todos = service.findAll();

        model.addAttribute("todos", todos);

        return "todo/list";

    }

}

  

这个示例中,控制器实现了一个简单的REST服务,以从 "待办事项 "列表中获取项目。它依赖于一个TodoService,其中包含业务逻辑。单元测试

为了测试findAll方法,咱们须要一个JUnit测试,它能够完成如下工做测试

  • Spring容器中配置被测试的ControllerTodoController所依赖的TodoService
  • findAll处理方法发送一个有效的请求。
  • 验证响应的元素,包括返回值("todo/list")和Model属性 "todos"

一个Spring MVC Junit测试的例子多是这样的ui

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration

public class TodoControllerTest {

    @Autowired

    TodoController controller;

 

    @Autowired

    TodoService todoService;

 

    MockMvc mockMvc;

 

    @Before

    public void setup() {

        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();

    }

 

    @Configuration

    static class Config {

        @Bean

        public TodoController getTodoController() {

            return new TodoController();

        }

 

        @Bean

        public TodoService getTodoService() {

            return new TodoService();

        }

    }

 

    @Test

    public void testFindAll() throws Exception {

        mockMvc.perform(get("/")).andExpect(view().name("todo/list"));

    }

}

  

上面的例子是一个很是简单的测试——但仍是有不少“样板”代码要写,有不少事情要作。在这个例子中,咱们使用一个内部的Configuration类为Spring配置了一个控制器和它的服务,而后使用MockMvc函数向处理程序发送请求。而后,咱们使用MockMvc函数向处理者方法发送请求(使用perform),并使用andExpect验证返回的视图名称。

上面的测试有什么问题吗?其实没什么——但想象一下一个更复杂的控制器方法,有多个处理方法,接受更多的参数并产生更多的输出。编写测试会花费更多的时间,特别是若是良好的测试覆盖率很重要的话。此外,大多数真实的测试须要更多的配置(XML或类配置、会话和环境、安全等)。

使用Parasoft Jtest生成Spring测试

Parasoft Jtest的单元测试助手能够帮助开发人员以多种方式编写Spring测试

  1. 自动快速生成Spring MVC测试的模板代码
  2. 自动生成参数化测试,提升测试覆盖率
  3. 模拟依赖关系,以隔离辅助方法并简化测试
  4. 在运行时收集覆盖率数据并分析测试流程
  5. 为改进测试提供建议,并提供快速修补办法

自动生成测试

Parasoft Jtest中生成Spring测试是很直接的——只需在你的IDE中为你的控制器选择一个Spring处理方法,并选择一个测试建立动做

选择Regular SpringParameterized Spring会自动为你生成模板化的Spring MVC测试,包括Configuration类(以及你的控制器所依赖的全部Bean)。mockMvc.perform调用也被添加进来,并被预先配置为调用建立测试的处理方法。Jtest 单元测试助手甚至增长了一些例子断言,你能够取消注释和配置。

Parasoft Jtest支持使用XML或类配置生成测试,经过在偏好设置中设置 "ContextConfiguration attributes for Spring tests "选项。

模拟依赖性

在单元测试中管理依赖关系是相当重要的,由于大部分的复杂性和工做来自于隔离被测单元。Jtest单元测试助手默认使用MockitoPowerMockito来模拟依赖关系(若是你不但愿这样,能够在偏好设置中禁用)。模拟依赖关系容许测试控制这些依赖关系,将处理程序方法与应用程序的其余部分隔离开来,以便将测试工做集中在处理程序上。在咱们的示例处理程序中,findAll方法是在TodoService上被调用的——若是咱们使用一个真正的TodoService,咱们就有效地测试了TodoControllerTodoService。这多是咱们在集成测试中想要的,但不是在单元测试中想要的。在测试中模拟TodoService.findAll的响应,可让咱们把测试工做集中在处理方法上。

若是你想了解更多关于在Spring测试中模拟依赖关系的信息,请阅读个人下一篇文章。)

Spring Boot

因为Spring BootBean提供了简化的配置,以及额外的测试注释,因此当单元测试助理在的项目中检测到Spring Boot时,会生成略有不一样的测试。例如,MockMvc是自动链接的,依赖关系使用@MockBean进行模拟,并使用@SpringBootTest注解。

运行测试和分析结果

你可使用任何普通的JUnit运行器运行生成的测试。Parasoft Jtest提供了运行JUnit和分析测试的工具栏操做。

测试运行后,会显示测试执行流程,单元测试助手会提出改进测试的建议,并在IDE中报告

提供处理程序方法输入

处理程序方法一般被配置为接受路径、查询或其余参数做为方法的参数。要测试MVC处理程序方法,可使用MockMvc来构建路径/查询和调用该方法所需的任何其余参数。

Jtest单元测试助理会自动配置mockMvc.perform调用来调用处理程序方法。单个参数在测试中显示为局部变量(或参数化测试中的参数),须要配置这些参数才能使测试正确运行。

例如(下文单元测试助手缩写为UTA

@Test public void testGetPerson() throws Throwable {     // When     String id = ""; // UTA: Configure an appropriate parameter value since the tested method depends on it     ResultActions actions = mockMvc.perform(get("/people/" + id));

  

这里,须要配置 "id"字符串——若是没有,那么使用的路径将是"/people/"Spring将不会把提供的路径匹配到合适的处理方法。

class="p1>单元测试助手会寻找各类类型的处理程序方法参数,并经过如下方式自动为它们准备测试

  • HttpSession(增长一个setAttribute()调用的例子)
  • 头部(增长一个header()调用)
  • 请求主体(添加一个payload变量和content()调用)
  • 认证(在setup方法中添加了一个实例,以及一个principal()调用)

运行一个不会致使处理程序方法被调用的测试,会产生相似下面的建议:

验证处理程序方法的输出

根据处理程序方法要提供给调用者的内容,它可能返回多种类型。大多数状况下,处理方法会返回一个ModelAndView(或相似的对象,如ModelRedirectView)来为页面提供服务,或者返回某种类型的ResponseEntity(有时只是要序列化的原始对象)。这个响应能够访问Spring MVC测试框架进行验证。

例如,Jtest单元测试助理为一个返回ModelAndView的处理方法添加了如下断言

  // When

  String id = "1";

  ResultActions actions = mockMvc.perform(get("/people/" + id));

 

  // Then

  // actions.andExpect(status().isOk());

  // actions.andExpect(header().string("", ""));

  // actions.andExpect(view().name(""));

  // actions.andExpect(model().attribute("", ""));

  

一旦测试生成,你就能够取消对这些断言的注释并填充值,以快速创建一个有用的和有价值的测试。若是一个断言在运行时失败了,单元测试助手提供了一个建议和快速修复,以自动更新预期值或简单地删除断言。为了快速设置一个正确的断言值,你能够取消对断言的注释,让它失败,而后使用快速修复来设置正确的指望值。

总结

Spring(结合Spring Boot)是领先的企业级Java应用框架,所以须要适当的测试水平,以确保用它构建的应用的质量和安全性。但遗憾的是,这种水平的测试目前尚未实现,主要是因为缺少时间和须要大量的人工编码和维护。Parasoft Jtest 单元测试助手不只提供了单元测试自动化,还提供了指导性的测试建立和依赖性管理,以加速测试建立和减小维护。

要了解更多信息,请阅读单元测试助手如何利用模拟框架帮助进行依赖性管理

相关文章
相关标签/搜索