我尝试使用resource class对Java Dropwizard中的Spock testing framework进行单元测试。
将Todo
发布到/
应将Todo
添加到数据库并返回
添加的Todo
。当我运行代码时,代码按预期工作,我只是无法弄清楚如何测试它。
我想验证三件事:
Todo
TodoStore.save
被调用一次。以下测试仅适用于第3项。如何修复第1项和第2项?
完整的工作代码可在相关提交的Github处获得。
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
response.getStatusInfo() == Response.Status.OK
// PASSES
1 * todoStore.save(_ as Todo)
}
}
@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);
}
}
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);
}
}
答案 0 :(得分:0)
我应该仔细检查文档。
来自Combining Mocking and Stubbing上的Spock文档。
当模拟和存根相同的方法调用时,它们必须在相同的交互中发生。特别是,以下Mockito风格将存根和模拟拆分为两个单独的语句将不工作:
我的具体示例的解决方案是在todoStore.save
块中存根then
,如下所示:
def "Adding a todo increases number of Todos"() {
given: "no todos in TodoStore"
Todo todo = new Todo(1, "title", null, null, null)
when: "we add a Todo"
def response = resources.client().target("/")
.request(APPLICATION_JSON_TYPE)
.post(entity(todo, APPLICATION_JSON_TYPE))
then:
// How do you test that the returned Todo is the same?
response.getStatusInfo() == Response.Status.OK
1 * todoStore.save(_ as Todo) >> todo
}
仍然不确定如何验证问题#1,响应返回相同的Todo对象。