diff --git a/support/maven-archetype/src/main/resources/archetype-resources/pom.xml b/support/maven-archetype/src/main/resources/archetype-resources/pom.xml index d332c69a3..72c608fe8 100644 --- a/support/maven-archetype/src/main/resources/archetype-resources/pom.xml +++ b/support/maven-archetype/src/main/resources/archetype-resources/pom.xml @@ -10,22 +10,23 @@ 4.3.0-SNAPSHOT - 4.0.0.RELEASE + 4.0.2.RELEASE 4.3.1.Final - 1.4.2.RELEASE - 7.0.50 + 1.4.4.RELEASE + 7.0.52 2.4.2 1.2.2 - 5.0.2.Final + 5.0.3.Final 2.3.1 - 1.7.5 - 1.0.13 + 1.7.4 + 1.7.6 + 1.1.1 3.2.1 - 16.0 + 16.0.1 4.11 1.5.0 1.9.5 - 2.39.0 + 2.40.0 7.6.14.v20131031 1.3.175 @@ -37,10 +38,10 @@ com.h2database h2 ${h2.version} - @@ -48,17 +49,17 @@ 3.0.0 - @@ -83,24 +84,18 @@ org.springframework.data spring-data-jpa ${spring-data-jpa.version} - - - junit - junit-dep - - org.aspectj aspectjrt - 1.7.3 + ${aspectj.version} org.aspectj aspectjweaver - 1.7.3 + ${aspectj.version} runtime @@ -320,12 +315,12 @@ - @@ -356,12 +351,7 @@ net.sf.ehcache ehcache-core - 2.6.6 - - - commons-codec - commons-codec - 1.9 + 2.6.8 diff --git a/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/rest/TaskRestController.java b/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/rest/TaskRestController.java index cabf208c3..40cd0eae9 100644 --- a/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/rest/TaskRestController.java +++ b/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/rest/TaskRestController.java @@ -1,100 +1,100 @@ #set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) -/******************************************************************************* - * Copyright (c) 2005, 2014 springside.github.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - *******************************************************************************/ -package ${package}.rest; - -import java.net.URI; -import java.util.List; - -import javax.validation.Validator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.UriComponentsBuilder; -import ${package}.entity.Task; -import ${package}.service.task.TaskService; -import org.springside.modules.beanvalidator.BeanValidators; -import org.springside.modules.web.MediaTypes; - -/** - * Task的Restful API的Controller. - * - * @author calvin - */ -@RestController -@RequestMapping(value = "/api/v1/task") -public class TaskRestController { - - private static Logger logger = LoggerFactory.getLogger(TaskRestController.class); - - @Autowired - private TaskService taskService; - - @Autowired - private Validator validator; - - @RequestMapping(method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8) - public List list() { - return taskService.getAllTask(); - } - - @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8) - public Task get(@PathVariable("id") Long id) { - Task task = taskService.getTask(id); - if (task == null) { - String message = "任务不存在(id:" + id + ")"; - logger.warn(message); - throw new RestException(HttpStatus.NOT_FOUND, message); - } - return task; - } - - @RequestMapping(method = RequestMethod.POST, consumes = MediaTypes.JSON) - public ResponseEntity create(@RequestBody Task task, UriComponentsBuilder uriBuilder) { - // 调用JSR303 Bean Validator进行校验, 异常将由RestExceptionHandler统一处理. - BeanValidators.validateWithException(validator, task); - - // 保存任务 - taskService.saveTask(task); - - // 按照Restful风格约定,创建指向新任务的url, 也可以直接返回id或对象. - Long id = task.getId(); - URI uri = uriBuilder.path("/api/v1/task/" + id).build().toUri(); - HttpHeaders headers = new HttpHeaders(); - headers.setLocation(uri); - - return new ResponseEntity(headers, HttpStatus.CREATED); - } - - @RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = MediaTypes.JSON) - public ResponseEntity update(@RequestBody Task task) { - // 调用JSR303 Bean Validator进行校验, 异常将由RestExceptionHandler统一处理. - BeanValidators.validateWithException(validator, task); - // 保存 - taskService.saveTask(task); - - // 按Restful约定,返回204状态码, 无内容. 也可以返回200状态码. - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - - @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) - @ResponseStatus(HttpStatus.NO_CONTENT) - public void delete(@PathVariable("id") Long id) { - taskService.deleteTask(id); - } -} +/******************************************************************************* + * Copyright (c) 2005, 2014 springside.github.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + *******************************************************************************/ +package ${package}.rest; + +import java.net.URI; +import java.util.List; + +import javax.validation.Validator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.util.UriComponentsBuilder; +import ${package}.entity.Task; +import ${package}.service.task.TaskService; +import org.springside.modules.beanvalidator.BeanValidators; +import org.springside.modules.web.MediaTypes; + +/** + * Task的Restful API的Controller. + * + * @author calvin + */ +@RestController +@RequestMapping(value = "/api/v1/task") +public class TaskRestController { + + private static Logger logger = LoggerFactory.getLogger(TaskRestController.class); + + @Autowired + private TaskService taskService; + + @Autowired + private Validator validator; + + @RequestMapping(method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8) + public List list() { + return taskService.getAllTask(); + } + + @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8) + public Task get(@PathVariable("id") Long id) { + Task task = taskService.getTask(id); + if (task == null) { + String message = "任务不存在(id:" + id + ")"; + logger.warn(message); + throw new RestException(HttpStatus.NOT_FOUND, message); + } + return task; + } + + @RequestMapping(method = RequestMethod.POST, consumes = MediaTypes.JSON) + public ResponseEntity create(@RequestBody Task task, UriComponentsBuilder uriBuilder) { + // 调用JSR303 Bean Validator进行校验, 异常将由RestExceptionHandler统一处理. + BeanValidators.validateWithException(validator, task); + + // 保存任务 + taskService.saveTask(task); + + // 按照Restful风格约定,创建指向新任务的url, 也可以直接返回id或对象. + Long id = task.getId(); + URI uri = uriBuilder.path("/api/v1/task/" + id).build().toUri(); + HttpHeaders headers = new HttpHeaders(); + headers.setLocation(uri); + + return new ResponseEntity(headers, HttpStatus.CREATED); + } + + @RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = MediaTypes.JSON) + // 按Restful风格约定,返回204状态码, 无内容. 也可以返回200状态码. + @ResponseStatus(HttpStatus.NO_CONTENT) + public void update(@RequestBody Task task) { + // 调用JSR303 Bean Validator进行校验, 异常将由RestExceptionHandler统一处理. + BeanValidators.validateWithException(validator, task); + + // 保存任务 + taskService.saveTask(task); + } + + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + @ResponseStatus(HttpStatus.NO_CONTENT) + public void delete(@PathVariable("id") Long id) { + taskService.deleteTask(id); + } +} diff --git a/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/service/task/TaskService.java b/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/service/task/TaskService.java index dc2cfe4ec..9d624f43e 100644 --- a/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/service/task/TaskService.java +++ b/support/maven-archetype/src/main/resources/archetype-resources/src/main/java/service/task/TaskService.java @@ -1,88 +1,88 @@ #set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) -/******************************************************************************* - * Copyright (c) 2005, 2014 springside.github.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - *******************************************************************************/ -package ${package}.service.task; - -import java.util.List; -import java.util.Map; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; -import ${package}.entity.Task; -import ${package}.repository.TaskDao; -import org.springside.modules.persistence.DynamicSpecifications; -import org.springside.modules.persistence.SearchFilter; -import org.springside.modules.persistence.SearchFilter.Operator; - -//Spring Bean的标识. -@Component -// 默认将类中的所有public函数纳入事务管理. -@Transactional -public class TaskService { - - private TaskDao taskDao; - - public Task getTask(Long id) { - return taskDao.findOne(id); - } - - public void saveTask(Task entity) { - taskDao.save(entity); - } - - public void deleteTask(Long id) { - taskDao.delete(id); - } - - public List getAllTask() { - return (List) taskDao.findAll(); - } - - public Page getUserTask(Long userId, Map searchParams, int pageNumber, int pageSize, - String sortType) { - PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType); - Specification spec = buildSpecification(userId, searchParams); - - return taskDao.findAll(spec, pageRequest); - } - - /** - * 创建分页请求. - */ - private PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) { - Sort sort = null; - if ("auto".equals(sortType)) { - sort = new Sort(Direction.DESC, "id"); - } else if ("title".equals(sortType)) { - sort = new Sort(Direction.ASC, "title"); - } - - return new PageRequest(pageNumber - 1, pagzSize, sort); - } - - /** - * 创建动态查询条件组合. - */ - private Specification buildSpecification(Long userId, Map searchParams) { - Map filters = SearchFilter.parse(searchParams); - filters.put("user.id", new SearchFilter("user.id", Operator.EQ, userId)); - Specification spec = DynamicSpecifications.bySearchFilter(filters.values(), Task.class); - return spec; - } - - @Autowired - public void setTaskDao(TaskDao taskDao) { - this.taskDao = taskDao; - } -} +/******************************************************************************* + * Copyright (c) 2005, 2014 springside.github.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + *******************************************************************************/ +package ${package}.service.task; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import ${package}.entity.Task; +import ${package}.repository.TaskDao; +import org.springside.modules.persistence.DynamicSpecifications; +import org.springside.modules.persistence.SearchFilter; +import org.springside.modules.persistence.SearchFilter.Operator; + +// Spring Bean的标识. +@Component +// 类中所有public函数都纳入事务管理的标识. +@Transactional +public class TaskService { + + private TaskDao taskDao; + + public Task getTask(Long id) { + return taskDao.findOne(id); + } + + public void saveTask(Task entity) { + taskDao.save(entity); + } + + public void deleteTask(Long id) { + taskDao.delete(id); + } + + public List getAllTask() { + return (List) taskDao.findAll(); + } + + public Page getUserTask(Long userId, Map searchParams, int pageNumber, int pageSize, + String sortType) { + PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType); + Specification spec = buildSpecification(userId, searchParams); + + return taskDao.findAll(spec, pageRequest); + } + + /** + * 创建分页请求. + */ + private PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) { + Sort sort = null; + if ("auto".equals(sortType)) { + sort = new Sort(Direction.DESC, "id"); + } else if ("title".equals(sortType)) { + sort = new Sort(Direction.ASC, "title"); + } + + return new PageRequest(pageNumber - 1, pagzSize, sort); + } + + /** + * 创建动态查询条件组合. + */ + private Specification buildSpecification(Long userId, Map searchParams) { + Map filters = SearchFilter.parse(searchParams); + filters.put("user.id", new SearchFilter("user.id", Operator.EQ, userId)); + Specification spec = DynamicSpecifications.bySearchFilter(filters.values(), Task.class); + return spec; + } + + @Autowired + public void setTaskDao(TaskDao taskDao) { + this.taskDao = taskDao; + } +} diff --git a/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/applicationContext.xml b/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/applicationContext.xml index 78d193125..c39f19d53 100644 --- a/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/applicationContext.xml +++ b/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/applicationContext.xml @@ -74,10 +74,8 @@ + - - - diff --git a/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/logback.xml b/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/logback.xml index f869b84a4..cee62b25e 100644 --- a/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/logback.xml +++ b/support/maven-archetype/src/main/resources/archetype-resources/src/main/resources/logback.xml @@ -1,32 +1,32 @@ #set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - logs/${artifactId}.log - - logs/${artifactId}.%d{yyyy-MM-dd}.log - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - - - + + + + + %date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + /tmp/logs/${artifactId}.log + + /tmp/logs/${artifactId}.%d{yyyy-MM-dd}.log + + + %date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + \ No newline at end of file diff --git a/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/BaseSeleniumTestCase.java b/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/BaseSeleniumTestCase.java index 62b76332b..a5ddded22 100644 --- a/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/BaseSeleniumTestCase.java +++ b/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/BaseSeleniumTestCase.java @@ -1,70 +1,70 @@ #set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) -/******************************************************************************* - * Copyright (c) 2005, 2014 springside.github.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - *******************************************************************************/ -package ${package}.functional; - -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.rules.TestRule; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.springside.modules.test.selenium.Selenium2; -import org.springside.modules.test.selenium.SeleniumSnapshotRule; -import org.springside.modules.test.selenium.WebDriverFactory; - -/** - * 使用Selenium的功能测试基类. - * - * 在BaseFunctionalTestCase的基础上,在整个测试期间仅启动一次Selenium. - * - * @author calvin - */ -public class BaseSeleniumTestCase extends BaseFunctionalTestCase { - - protected static Selenium2 s; - - // 出错时截屏的规则 - @Rule - public TestRule snapshotRule = new SeleniumSnapshotRule(s); - - @BeforeClass - public static void initSelenium() throws Exception { - createSeleniumOnce(); - loginAsUserIfNecessary(); - } - - /** - * 创建Selenium,仅创建一次. - */ - protected static void createSeleniumOnce() throws Exception { - if (s == null) { - // 根据配置创建Selenium driver. - String driverName = propertiesLoader.getProperty("selenium.driver"); - - WebDriver driver = WebDriverFactory.createDriver(driverName); - - s = new Selenium2(driver, baseUrl); - s.setStopAtShutdown(); - } - } - - /** - * 登录管理员, 如果用户还没有登录. - */ - protected static void loginAsUserIfNecessary() { - s.open("/task"); - - if (s.getTitle().contains("登录页")) { - s.type(By.name("username"), "user"); - s.type(By.name("password"), "user"); - s.check(By.name("rememberMe")); - s.click(By.id("submit_btn")); - s.waitForTitleContains("任务管理"); - } - } -} +/******************************************************************************* + * Copyright (c) 2005, 2014 springside.github.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + *******************************************************************************/ +package ${package}.functional; + +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.rules.TestRule; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.springside.modules.test.selenium.Selenium2; +import org.springside.modules.test.selenium.SeleniumSnapshotRule; +import org.springside.modules.test.selenium.WebDriverFactory; + +/** + * 使用Selenium的功能测试基类. + * + * 在BaseFunctionalTestCase的基础上,在整个测试期间仅启动一次Selenium. + * + * @author calvin + */ +public class BaseSeleniumTestCase extends BaseFunctionalTestCase { + + protected static Selenium2 s; + + // 出错时截屏的规则 + @Rule + public TestRule snapshotRule = new SeleniumSnapshotRule(s); + + @BeforeClass + public static void initSelenium() throws Exception { + createSeleniumOnce(); + loginAsUserIfNecessary(); + } + + /** + * 创建Selenium,仅创建一次. + */ + protected static void createSeleniumOnce() throws Exception { + if (s == null) { + // 根据配置创建Selenium driver. + String driverName = propertiesLoader.getProperty("selenium.driver"); + + WebDriver driver = WebDriverFactory.createDriver(driverName); + + s = new Selenium2(driver, baseUrl); + s.setStopAtShutdown(); + } + } + + /** + * 登录管理员, 如果用户还没有登录. + */ + protected static void loginAsUserIfNecessary() { + s.open("/task"); + + if (s.getTitle().contains("登录页")) { + s.type(By.name("username"), "user"); + s.type(By.name("password"), "user"); + s.check(By.name("rememberMe")); + s.click(By.id("submit_btn")); + s.waitForTitleContains("任务管理"); + } + } +} diff --git a/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/rest/TaskRestFT.java b/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/rest/TaskRestFT.java index d12a270c0..3830e6e8d 100644 --- a/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/rest/TaskRestFT.java +++ b/support/maven-archetype/src/main/resources/archetype-resources/src/test/functional/functional/rest/TaskRestFT.java @@ -1,135 +1,129 @@ #set( $symbol_pound = '#' ) #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) -/******************************************************************************* - * Copyright (c) 2005, 2014 springside.github.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - *******************************************************************************/ -package ${package}.functional.rest; - -import static org.assertj.core.api.Assertions.*; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.springframework.http.HttpStatus; -import org.springframework.web.client.HttpStatusCodeException; -import org.springframework.web.client.RestTemplate; -import ${package}.data.TaskData; -import ${package}.entity.Task; -import ${package}.functional.BaseFunctionalTestCase; -import org.springside.modules.mapper.JsonMapper; -import org.springside.modules.test.category.Smoke; - -/** - * 任务管理的功能测试, 测试页面JavaScript及主要用户故事流程. - * - * @author calvin - */ -public class TaskRestFT extends BaseFunctionalTestCase { - - private final RestTemplate restTemplate = new RestTemplate(); - - private final JsonMapper jsonMapper = new JsonMapper(); - - private static class TaskList extends ArrayList { - } - - private static String resoureUrl; - - @BeforeClass - public static void initUrl() { - resoureUrl = baseUrl + "/api/v1/task"; - } - - /** - * 查看任务列表. - */ - @Test - @Category(Smoke.class) - public void listTasks() { - TaskList tasks = restTemplate.getForObject(resoureUrl, TaskList.class); - assertThat(tasks).hasSize(5); - assertThat(tasks.get(0).getTitle()).isEqualTo("Study PlayFramework 2.0"); - } - - /** - * 获取任务. - */ - @Test - @Category(Smoke.class) - public void getTask() { - Task task = restTemplate.getForObject(resoureUrl + "/{id}", Task.class, 1L); - assertThat(task.getTitle()).isEqualTo("Study PlayFramework 2.0"); - } - - /** - * 创建/更新/删除任务. - */ - @Test - @Category(Smoke.class) - public void createUpdateAndDeleteTask() { - - // create - Task task = TaskData.randomTask(); - - URI taskUri = restTemplate.postForLocation(resoureUrl, task); - System.out.println(taskUri.toString()); - Task createdTask = restTemplate.getForObject(taskUri, Task.class); - assertThat(createdTask.getTitle()).isEqualTo(task.getTitle()); - - // update - String id = StringUtils.substringAfterLast(taskUri.toString(), "/"); - task.setId(new Long(id)); - task.setTitle(TaskData.randomTitle()); - - restTemplate.put(taskUri, task); - - Task updatedTask = restTemplate.getForObject(taskUri, Task.class); - assertThat(updatedTask.getTitle()).isEqualTo(task.getTitle()); - - // delete - restTemplate.delete(taskUri); - - try { - restTemplate.getForObject(taskUri, Task.class); - fail("Get should fail while feth a deleted task"); - } catch (HttpStatusCodeException e) { - assertThat(e.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } - } - - @Test - public void invalidInput() { - - // create - Task titleBlankTask = new Task(); - try { - restTemplate.postForLocation(resoureUrl, titleBlankTask); - fail("Create should fail while title is blank"); - } catch (HttpStatusCodeException e) { - assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); - Map messages = jsonMapper.fromJson(e.getResponseBodyAsString(), Map.class); - assertThat(messages).hasSize(1); - assertThat(messages.get("title")).isIn("may not be empty", "不能为空"); - } - - // update - titleBlankTask.setId(1L); - try { - restTemplate.put(resoureUrl + "/1", titleBlankTask); - fail("Update should fail while title is blank"); - } catch (HttpStatusCodeException e) { - assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); - Map messages = jsonMapper.fromJson(e.getResponseBodyAsString(), Map.class); - assertThat(messages).hasSize(1); - assertThat(messages.get("title")).isIn("may not be empty", "不能为空"); - } - } -} +/******************************************************************************* + * Copyright (c) 2005, 2014 springside.github.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + *******************************************************************************/ +package ${package}.functional.rest; + +import static org.assertj.core.api.Assertions.*; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.springframework.http.HttpStatus; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestTemplate; +import ${package}.data.TaskData; +import ${package}.entity.Task; +import ${package}.functional.BaseFunctionalTestCase; +import org.springside.modules.mapper.JsonMapper; +import org.springside.modules.test.category.Smoke; + +/** + * 任务管理的功能测试, 测试页面JavaScript及主要用户故事流程. + * + * @author calvin + */ +public class TaskRestFT extends BaseFunctionalTestCase { + + private static String resourceUrl = baseUrl + "/api/v1/task"; + + private final RestTemplate restTemplate = new RestTemplate(); + private final JsonMapper jsonMapper = new JsonMapper(); + + /** + * 查看任务列表. + */ + @Test + @Category(Smoke.class) + public void listTasks() { + TaskList tasks = restTemplate.getForObject(resourceUrl, TaskList.class); + assertThat(tasks).hasSize(5); + assertThat(tasks.get(0).getTitle()).isEqualTo("Study PlayFramework 2.0"); + } + + /** + * 获取任务. + */ + @Test + @Category(Smoke.class) + public void getTask() { + Task task = restTemplate.getForObject(resourceUrl + "/{id}", Task.class, 1L); + assertThat(task.getTitle()).isEqualTo("Study PlayFramework 2.0"); + } + + /** + * 创建/更新/删除任务. + */ + @Test + @Category(Smoke.class) + public void createUpdateAndDeleteTask() { + + // create + Task task = TaskData.randomTask(); + + URI createdTaskUri = restTemplate.postForLocation(resourceUrl, task); + System.out.println(createdTaskUri.toString()); + Task createdTask = restTemplate.getForObject(createdTaskUri, Task.class); + assertThat(createdTask.getTitle()).isEqualTo(task.getTitle()); + + // update + String id = StringUtils.substringAfterLast(createdTaskUri.toString(), "/"); + task.setId(new Long(id)); + task.setTitle(TaskData.randomTitle()); + + restTemplate.put(createdTaskUri, task); + + Task updatedTask = restTemplate.getForObject(createdTaskUri, Task.class); + assertThat(updatedTask.getTitle()).isEqualTo(task.getTitle()); + + // delete + restTemplate.delete(createdTaskUri); + + try { + restTemplate.getForObject(createdTaskUri, Task.class); + fail("Get should fail while feth a deleted task"); + } catch (HttpStatusCodeException e) { + assertThat(e.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + } + } + + @Test + public void invalidInput() { + + // create + Task titleBlankTask = new Task(); + try { + restTemplate.postForLocation(resourceUrl, titleBlankTask); + fail("Create should fail while title is blank"); + } catch (HttpStatusCodeException e) { + assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + Map messages = jsonMapper.fromJson(e.getResponseBodyAsString(), Map.class); + assertThat(messages).hasSize(1); + assertThat(messages.get("title")).isIn("may not be empty", "不能为空"); + } + + // update + titleBlankTask.setId(1L); + try { + restTemplate.put(resourceUrl + "/1", titleBlankTask); + fail("Update should fail while title is blank"); + } catch (HttpStatusCodeException e) { + assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + Map messages = jsonMapper.fromJson(e.getResponseBodyAsString(), Map.class); + assertThat(messages).hasSize(1); + assertThat(messages.get("title")).isIn("may not be empty", "不能为空"); + } + } + + // ArrayList在RestTemplate转换时不好表示,创建一个类来表达它是最简单的。 + private static class TaskList extends ArrayList { + } +}