Skip to content

Instantly share code, notes, and snippets.

@BenArunski
Last active February 17, 2016 17:03
Show Gist options
  • Save BenArunski/b27566dbdc9238f9459c to your computer and use it in GitHub Desktop.
Save BenArunski/b27566dbdc9238f9459c to your computer and use it in GitHub Desktop.
Spring RestController + Rest-Assured + Spock
...
dependencies {
...
testCompile "org.hamcrest:hamcrest-library:1.3"
testCompile "org.hamcrest:hamcrest-core:1.3"
testCompile 'com.jayway.restassured:rest-assured:2.8.0'
testCompile 'com.jayway.restassured:spring-mock-mvc:2.8.0'
}
...
package hello;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR, reason = "There was an unexpected server exception")
public class InternalServerErrorException extends RuntimeException {
private static final long serialVersionUID = 1L;
}
package hello;
public class Todo {
private String text;
private boolean done;
public Todo() {
}
public Todo(String text, boolean done) {
this.text = text;
this.done = done;
}
public void put(Todo todo) {
text = todo.text;
done = todo.done;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (done ? 1231 : 1237);
result = prime * result + ((text == null) ? 0 : text.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Todo other = (Todo) obj;
if (done != other.done)
return false;
if (text == null) {
if (other.text != null)
return false;
} else if (!text.equals(other.text))
return false;
return true;
}
}
package hello;
import static java.util.Collections.synchronizedList;
import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.SC_UNPROCESSABLE_ENTITY;
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.BooleanUtils;
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.RestController;
@RestController
public class TodoController {
// List is just for demo purposes
private final List<Todo> todos = synchronizedList(new ArrayList<>());
@RequestMapping(path = "/todos/{user}", method = { GET }, produces = "application/json")
public List<Todo> readAllForUser(@PathVariable("user") String user, HttpServletResponse response) {
if ("ben".equalsIgnoreCase(user)) {
response.setStatus(SC_OK);
return todos;
} else {
response.setStatus(SC_NOT_FOUND);
return new ArrayList<>();
}
}
@RequestMapping(path = "/todo/{id}", method = { GET }, produces = "application/json")
public Todo read(@PathVariable("id") int id, HttpServletResponse response) {
try {
response.setStatus(SC_OK);
return todos.get(id);
} catch (IndexOutOfBoundsException e) {
response.setStatus(SC_NOT_FOUND);
return null;
} catch (Exception e) {
throw new InternalServerErrorException();
}
}
@RequestMapping(path = "/todo", method = { POST }, produces = "application/json")
public List<Todo> create(@RequestBody Map<String, String> body, HttpServletResponse response) {
try {
if (body.get("text") != null) {
boolean done = BooleanUtils.toBoolean(body.get("done"));
todos.add(new Todo(body.get("text"), done));
response.setStatus(SC_OK);
} else {
response.setStatus(SC_UNPROCESSABLE_ENTITY);
}
} catch (Exception e) {
throw new InternalServerErrorException();
}
return todos;
}
@RequestMapping(path = "/todo", method = { DELETE }, produces = "application/json")
public synchronized List<Todo> deleteByObject(@RequestBody Todo body, HttpServletResponse response) {
try {
if (todos.remove(body)) {
response.setStatus(SC_OK);
} else {
response.setStatus(SC_NOT_FOUND);
}
} catch (Exception e) {
throw new InternalServerErrorException();
}
return todos;
}
@RequestMapping(path = "/todo/{id}", method = { DELETE }, produces = "application/json")
public List<Todo> deleteById(@PathVariable("id") int id, HttpServletResponse response) {
try {
todos.remove(id);
response.setStatus(SC_OK);
} catch (IndexOutOfBoundsException e) {
response.setStatus(SC_NOT_FOUND);
} catch (Exception e) {
throw new InternalServerErrorException();
}
return todos;
}
@RequestMapping(path = "/todo/{id}", method = { PUT }, produces = "application/json")
public List<Todo> update(@PathVariable("id") int id, @RequestBody Todo body, HttpServletResponse response) {
try {
todos.get(id).put(body);
response.setStatus(SC_OK);
} catch (IndexOutOfBoundsException e) {
response.setStatus(SC_NOT_FOUND);
} catch (Exception e) {
throw new InternalServerErrorException();
}
return todos;
}
@RequestMapping(path = "/todo", method = { PUT }, produces = "application/json")
public List<Todo> updateByObject(@RequestBody List<Todo> body, HttpServletResponse response) {
try {
if (body.size() != 2) {
response.setStatus(SC_BAD_REQUEST);
} else {
response.setStatus(SC_NOT_FOUND);
todos.stream()
.filter(it -> it.equals(body.get(0)))
.findFirst()
.ifPresent(it -> {
it.put(body.get(1));
response.setStatus(SC_OK);
});
}
} catch (Exception e) {
throw new InternalServerErrorException();
}
return todos;
}
}
package initial
import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.given
import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.when
import static org.hamcrest.Matchers.*
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification
import groovy.json.JsonBuilder
import hello.Todo
import hello.TodoController
import spock.lang.Specification
/**
* adapted from the final example on https://gist.github.com/kpiwko/5612949
*/
class todoControllerSpec extends Specification {
MockMvcRequestSpecification request = given().contentType("application/json")
JsonBuilder json = new JsonBuilder()
def setup() {
RestAssuredMockMvc.standaloneSetup(new TodoController())
}
def 'get all for a user - empty' () {
given: 'get all for user'
def response = given().spec(request).get '/todos/ben'
def body = response.body()
expect: 'http success'
response.statusCode() == 200
and: 'an empty set of todos'
body.path('$').size() == 0
}
def 'create without done variable' () {
given: 'a todo body'
request.body json(text : 'the text')
when: 'a create request'
def response = given().spec(request).post "/todo"
def body = response.body()
then: 'http success'
response.statusCode() == 200
and: 'one item is returned'
body.path('$').size() == 1
and: 'my specified item is returned'
body.path('[0].text') == 'the text'
and: '"done" defaults false'
body.path('[0].done') == false
}
def 'get all for user - populated list' () {
given: 'two todos'
request.body json(text: 'one', done: true)
given().spec(request).post '/todo'
request.body json(text: 'two', done: false)
given().spec(request).post '/todo'
when: 'get all for user'
def response = given().spec(request).get '/todos/ben'
def body = response.body()
then: 'http success'
response.statusCode() == 200
and: 'two items are returned'
body.path('$').size() == 2
and: 'item 1 is returned'
Todo todo = body.path '[0]'
todo.text == 'one'
todo.done == true
and: 'item 2 is returned'
Todo todo2 = body.path '[1]'
todo2.text == 'two'
todo2.done == false
}
def 'update by id' () {
given: 'two todos'
request.body json(text: 'one', done: true)
given().spec(request).post '/todo'
request.body json(text: 'two', done: false)
given().spec(request).post '/todo'
when: 'update :1'
request.body json(text: 'updated one', done: true)
def response = given().spec(request).put '/todo/0'
def body = response.body()
then: 'http success'
response.statusCode() == 200
and: 'item 1 is returned, updated'
Todo todo = body.path '[0]'
todo.text == 'updated one'
todo.done == true
and: 'item 2 is returned'
Todo todo2 = body.path '[1]'
todo2.text == 'two'
todo2.done == false
}
def 'update by object' () {
given: 'two todos'
request.body json(text: 'one', done: true)
given().spec(request).post '/todo'
request.body json(text: 'two', done: false)
given().spec(request).post '/todo'
when: 'update "one"'
request.body(
json ([
[
text: 'one',
done: true
],
[
text: 'updated one',
done: true
]
])
)
def response = given().spec(request).put '/todo'
def body = response.body()
then: 'http success'
response.statusCode() == 200
and: 'item 1 is returned, updated'
Todo todo = body.path '[0]'
todo.text == 'updated one'
todo.done == true
and: 'item 2 is returned'
Todo todo2 = body.path '[1]'
todo2.text == 'two'
todo2.done == false
}
}
package initial;
import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.given;
import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.when;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import org.junit.Before;
import org.junit.Test;
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc;
import hello.TodoController;
/**
* Documentation: https://github.com/jayway/rest-assured/wiki/Usage#spring-mock-mvc-module
*
* Hints not in the official documentation: https://code.google.com/p/rest-assured/wiki/Usage#Request_Body
*/
public class TodoControllerTest {
@Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new TodoController());
}
@Test
public void canGetTodosForAUser() {
when()
.get("/todos/ben")
.then()
.statusCode(200)
.body("$", hasSize(0));
}
@Test
public void canSaveATodo() {
String jsonRequestBody = "{ \"text\" : \"the text\" }";
given()
.contentType("application/json")
.body(jsonRequestBody)
.when()
.post("/todo")
.then()
.statusCode(200)
.body("$", hasSize(1))
.body("[0].text", equalTo("the text"));
when()
.get("/todos/ben");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment