Hi all,
POSTing a `Todo` to `/` should add the `Todo` to the database and return the added `Todo`. The code works as intended when I run it, I just can't figure out how to test it.
I want to verify three things:
1. I get a `Todo` back from the POST
2. I get a OK (200) status.
3. `TodoStore.save` is called once.
The test below only works for item 3. How do I fix item 1 and 2?
The full working code is available at
Github at the relevant commit. The relevant sections are below.
### TodoResourceTest.groovy
class TodoResourceTest extends Specification {
TodoStore todoStore = Mock(TodoStore)
@Rule
ResourceTestRule resources = ResourceTestRule.builder()
.addResource(new TodoResource(todoStore))
.build()
def "Adding a todo increases number of Todos"() {
given: "no todos in TodoStore"
Todo todo = new Todo(1, "title", null, null, null)
todoStore.save(_ as Todo) >> todo
when: "we add a Todo"
def response = resources.client().target("/")
.request(APPLICATION_JSON_TYPE)
.post(entity(todo, APPLICATION_JSON_TYPE))
then:
// HELP: How do you test that the returned Todo is the same?
// FAILS: Why doesn't this pass, it's returning 204 (no content) instead of 200
// Why isn't is returning the todo as specified in the "given" block?
response.getStatusInfo() == Response.Status.OK
// PASSES
1 * todoStore.save(_ as Todo)
}
}
### TodoResource.java
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public final class TodoResource {
private final TodoStore todoStore;
@Inject
public TodoResource(TodoStore todoStore) {
this.todoStore = todoStore;
}
@Timed
@POST
public Todo addTodo(Todo todo) {
return todoStore.save(todo);
}
}
### TodoStore.java - this is mocked, so it shouldn't matter
public class TodoStore {
private final DSLContext db;
@Inject
public TodoStore(DSLContext db) {
this.db = db;
}
public Todo save(Todo todo) {
final TodoRecord todoRecord = db.newRecord(TODO, todo);
// id is determined by database, not user
todoRecord.changed(TODO.ID, false);
// url is determined based on id
todoRecord.setUrl(null);
if (todoRecord.getCompleted() == null) {
todoRecord.setCompleted(false);
}
todoRecord.store();
return todoRecord.into(Todo.class);
}
}