/* * Copyright 2012-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package org.springside.examples.bootapi.functional; import static org.assertj.core.api.Assertions.*; import java.util.ArrayList; import java.util.Map; import org.junit.Before; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.TestRestTemplate; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import org.springside.examples.bootapi.api.support.ErrorResult; import org.springside.examples.bootapi.domain.Book; import org.springside.examples.bootapi.dto.BookDto; import org.springside.examples.bootapi.repository.BookDao; import org.springside.examples.bootapi.service.exception.ErrorCode; import org.springside.modules.test.data.RandomData; import org.springside.modules.utils.mapper.JsonMapper; import com.google.common.collect.Maps; // 测试方法的执行顺序在不同JVM里是不固定的,此处设为按方法名排序,避免方法间数据影响的不确定性 @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class BookEndpointTest extends BaseFunctionalTest { // 注入Spring Context中的BookDao,实现白盒查询数据库实际情况 @Autowired private BookDao bookDao; private RestTemplate restTemplate; private JsonMapper jsonMapper = new JsonMapper(); private String resourceUrl; private String loginUrl; private String logoutUrl; @Before public void setup() { // TestRestTemplate与RestTemplate, 服务端返回非200返回码时,不会抛异常. restTemplate = new TestRestTemplate(); resourceUrl = "http://localhost:" + port + "/api/books"; loginUrl = "http://localhost:" + port + "/api/accounts/login"; logoutUrl = "http://localhost:" + port + "/api/accounts/logout"; } @Test public void listBook() { BookList tasks = restTemplate.getForObject(resourceUrl, BookList.class); assertThat(tasks).hasSize(3); BookDto firstBook = tasks.get(0); assertThat(firstBook.title).isEqualTo("Big Data日知录"); assertThat(firstBook.owner.name).isEqualTo("Calvin"); BookDto book = restTemplate.getForObject(resourceUrl + "/{id}", BookDto.class, 1L); assertThat(book.title).isEqualTo("Big Data日知录"); assertThat(book.owner.name).isEqualTo("Calvin"); } @Test public void applyRequest() { String token = login("calvin.xiao@springside.io"); ResponseEntity<String> response = restTemplate.getForEntity(resourceUrl + "/{id}/request?token={token}", String.class, 3L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); // 查询数据库状态 Book book = bookDao.findOne(3L); assertThat(book.borrower.id).isEqualTo(1L); assertThat(book.status).isEqualTo(Book.STATUS_REQUEST); // 回退操作 response = restTemplate.getForEntity(resourceUrl + "/{id}/cancel?token={token}", String.class, 3L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); logout(token); } @Test public void applyRequestWithError() { // 未设置token ResponseEntity<String> response = restTemplate.getForEntity(resourceUrl + "/{id}/request", String.class, 1L); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); ErrorResult errorResult = jsonMapper.fromJson(response.getBody(), ErrorResult.class); assertThat(errorResult.code).isEqualTo(ErrorCode.NO_TOKEN.code); Book book = bookDao.findOne(1L); assertThat(book.borrower).isNull(); // 设置错误token response = restTemplate.getForEntity(resourceUrl + "/{id}/request?token={token}", String.class, 1L, "abc"); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); errorResult = jsonMapper.fromJson(response.getBody(), ErrorResult.class); assertThat(errorResult.code).isEqualTo(ErrorCode.UNAUTHORIZED.code); book = bookDao.findOne(1L); assertThat(book.borrower).isNull(); // 自己借自己的书 String token = login("calvin.xiao@springside.io"); response = restTemplate.getForEntity(resourceUrl + "/{id}/request?token={token}", String.class, 1L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); errorResult = jsonMapper.fromJson(response.getBody(), ErrorResult.class); assertThat(errorResult.code).isEqualTo(ErrorCode.BOOK_OWNERSHIP_WRONG.code); book = bookDao.findOne(1L); assertThat(book.borrower).isNull(); logout(token); // 借一本已被申请借出的书 token = login("calvin.xiao@springside.io"); response = restTemplate.getForEntity(resourceUrl + "/{id}/request?token={token}", String.class, 3L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); response = restTemplate.getForEntity(resourceUrl + "/{id}/request?token={token}", String.class, 3L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); errorResult = jsonMapper.fromJson(response.getBody(), ErrorResult.class); assertThat(errorResult.code).isEqualTo(ErrorCode.BOOK_STATUS_WRONG.code); // 回退操作 response = restTemplate.getForEntity(resourceUrl + "/{id}/cancel?token={token}", String.class, 3L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); logout(token); } @Test public void fullBorrowProcess() { // 发起请求 String token = login("david.wang@springside.io"); ResponseEntity<String> response = restTemplate.getForEntity(resourceUrl + "/{id}/request?token={token}", String.class, 1L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); logout(token); // 确认借出 token = login("calvin.xiao@springside.io"); response = restTemplate.getForEntity(resourceUrl + "/{id}/confirm?token={token}", String.class, 1L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); // 确认归还 response = restTemplate.getForEntity(resourceUrl + "/{id}/return?token={token}", String.class, 1L, token); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); logout(token); } private String login(String user) { Map<String, String> map = Maps.newHashMap(); map.put("email", user); map.put("password", "springside"); ResponseEntity<Map> response = restTemplate.getForEntity(loginUrl + "?email={email}&password={password}", Map.class, map); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); return (String) response.getBody().get("token"); } public void logout(String token) { restTemplate.getForEntity(logoutUrl + "?token={token}", String.class, token); } private static BookDto randomBook() { BookDto book = new BookDto(); book.title = RandomData.randomName("Book"); return book; } // ArrayList<Task>在RestTemplate转换时不好表示,创建一个类来表达它是最简单的。 private static class BookList extends ArrayList<BookDto> { } }