Sinatra单元测试 - 用JSON主体发布

时间:2013-08-26 17:15:38

标签: ruby unit-testing sinatra rack-test

我正在尝试为使用Sinatra构建的REST API构建单元测试。现在我只想测试我的echo功能是否正常。 Echo使用POST并将从帖子返回完全相同的有效负载。我仍然是红宝石的新人,所以如果我不使用正确的术语,请原谅我。

以下是我要测试的代码:

post '/echo' do
  request.body.read
end

这是我要做的单元测试:

ENV['RACK_ENV'] = 'test'
require './rest_server'
require 'test/unit'
require 'rack/test'
require 'json'

class RestServer < Test::Unit::TestCase

  def app
    Sinatra::Application
  end

  def test_check_methods
    data = '{"dataIn": "hello"}'
    response = post '/echo', JSON.parse(data)
    assert.last_response.ok?
    assert(response.body == data)
  end
end

使用上面的代码,这是错误:

NoMethodError: undefined method `dataIn' for Sinatra::Application:Class
    /Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1285:in `block in compile!'
    /Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1285:in `each_pair'
    /Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1285:in `compile!'
    /Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1267:in `route'
    /Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1256:in `post'
    /Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1688:in `block (2 levels) in delegate'
    /Users/barrywilliams/RubymineProjects/project/rest_server_test.rb:20:in `test_check_methods'

如果我尝试不使用JSON.parse,我会

NoMethodError: undefined method `key?' for "{\"dataIn\": \"hello\"}":String
/Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1265:in `route'
/Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1256:in `post'
/Users/barrywilliams/.rvm/gems/ruby-1.9.3-p448/gems/sinatra-1.3.4/lib/sinatra/base.rb:1688:in `block (2 levels) in delegate'
/Users/barrywilliams/RubymineProjects/project/rest_server_test.rb:20:in `test_check_methods'

如果我尝试在data = 'hello'的位置进行,那么我会得到相同的undefined method 'key?'错误

我尝试过这个建议,没有成功: http://softwareblog.morlok.net/2010/12/18/testing-post-with-racktest/ 我得到一个错误,说post只需要2个参数,而不是3个。

因此,总而言之,我需要能够进行调用,让我正在测试的代码接收调用并返回响应,然后我需要能够读取该响应并验证它是原始数据。现在看起来它只是在打电话时卡住了。

谢谢, 百里

2 个答案:

答案 0 :(得分:3)

我做了一件有点相似的事情,它可能对你有帮助:

申请职位定义:

post '/' do
    data = JSON.parse request.body.read.to_s
    "Hello !\n#{data.to_s}"
end

.to_s是必要的,否则转换将不完全相同: - /

然后在测试文件上:

class RootPostTest < Test::Unit::TestCase
    include Rack::Test::Methods
    def app
        Sinatra::Application
    end

    def test_return_the_parameters
        data = {
            'reqID' => 1,
            'signedReqID' => "plop",
            'cert' => "mycert"
        }
        post '/', data.to_json, "CONTENT_TYPE" => "application/json"
        assert last_response.ok?
        body_espected = "Hello !\n#{JSON.parse(data.to_json).to_s}"
        assert_equal last_response.body, body_espected
    end
end

希望它对你有所帮助。

答案 1 :(得分:2)

Rack Test将返回last_response.body中的响应正文,无需将其保存到变量中。你也没有回复你发送的内容 - 你给出的代码中的data是JSON,但是你把它转换为哈希并发布了,所以它不会与回来的内容相匹配。如果你想这样做,可以发送JSON,或者将它转换为Sinatra路由中的JSON(更多信息见https://stackoverflow.com/a/12138793/335847)。

在Sinatra应用程序中:

require 'json'

post '/echo' do
  # Don't use request.body.read as you're not posting JSON
  params.to_json
end

并在测试文件中:

def test_check_methods
  data = '{"dataIn": "hello"}'
  post '/echo', JSON.parse(data)
  assert.last_response.ok?
  assert(last_response.body == data)
end

如果您最终想要发布JSON(我认为如果它很容易转换或者已经将数据作为哈希值通常不是一个好主意)那么请使用:provides => "json"作为condition to the route,考虑使用Rack::Test::Accepts让生活更容易为此编写测试(注意:这是我写的宝石的无耻插件;)