如何在Rails/Capybara/Cucumber或Rspec中测试文章

12
我正在使用rspec、cucumber和capybara,希望找到一种方法来测试恶意用户无法入侵表单并提交到没有权限的url。我已经使用cancan设置了我的权限,这应该可以工作,但是唯一的测试方法就是自己入侵表单。
如何自动化这种测试?使用webrat,我可以在rspec的单元测试中执行此操作,例如:
put :update, :user_id => @user.id, :id => @user_achievement.id
response.should contain("Error, you don't have permission to access that!") 

在capybara中,visit似乎只能执行get方法。我找不到其他方法,已经在各处搜索过了。
非常感谢任何帮助!谢谢。

这对我非常关键,因为我只是在寻找一种使用 post 方法测试我的 API 的方法。在旧的方式下,你可以使用 webrat,只需执行 visit '/', :post。下面的答案展示了如何使用 Capybara 实现。 - John Hinnegan
2个回答

8

我认为你可以使用rack-test来完成这个任务。 https://github.com/brynary/rack-test

在你的Gemfile文件中:

gem 'rack-test'

在你的env.rb文件中

module CapybaraApp
  def app; Capybara.app; end
end
World(CapybaraApp)
World(Rack::Test::Methods)

某处的步骤定义:

When /^I send a POST request to "([^"]*)"$/ do |path|
  post path
end

大部分我学到的内容都来自这里:http://www.anthonyeden.com/2010/11/testing-rest-apis-with-cucumber-and-rack-test 更新:我认为对于新版本的Rails和/或Cucumber,您可以跳过对env.rb文件的更改(不确定是哪个版本,我在我的新项目中不执行此操作,而且它也能正常工作)。

2
当我这样做时,我的路由消失了。 我突然开始收到未定义的本地变量或方法`new_user_session_path' for #Cucumber::Rails::World:0x81e5b128 (NameError)错误提示。 - John Hinnegan
幸运的是,我的所有东西都在 paths.rb 文件中,所以我只需要进行替换。谢谢。 - John Hinnegan
@John,你可能需要在你的features/support/paths.rb文件中加入'include Rails.application.routes.url_helpers'。我正在使用Rails3进行这个项目,所以如果你使用的是Rails2,语法可能会有所不同。 - Josh Crews
谢谢你的建议。我以为我已经解决了问题,但事实证明我没有。最终我回到了Webrat来测试我的应用程序。我知道Webrat对于测试REST API等方面来说有些“过度”,但是我确实需要一个浏览器组件来处理我的应用程序的其他部分,所以为什么不呢。 - John Hinnegan

2
与@Josh Crews的做法基本相同,我主要是基于这个链接:http://www.anthonyeden.com/2010/11/testing-rest-apis-with-cucumber-and-rack-test/#comment-159。但有两个显著的例外:1)我测试实际的响应体,2)我演示如何测试POST请求。下面是一个使用Rails 3.0.9的示例:
步骤:
# features/step_definitions/api_step.feature
When /^I send a GET request to "([^\"]*)"$/ do |url|
  authorize(User.last.email, "cucumber")

  header 'Accept', 'application/json'
  header 'Content-Type', 'application/json'

  get url
end

When /^I send a POST request to "([^\"]*)" with:$/ do |url, body|
  authorize(User.last.email, "cucumber")

  header 'Accept', 'application/json'
  header 'Content-Type', 'application/json'

  post url, body
end

Then /^the JSON response should have (\d+) "([^\"]*)" elements$/ do |number_of_children, name|
  page = JSON.parse(last_response.body)
  page.map { |d| d[name] }.length.should == number_of_children.to_i
end

Then /^I should receive the following JSON response:$/ do |expected_json|
  expected_json = JSON.parse(expected_json)
  response_json = JSON.parse(last_response.body)

  response_json.should == expected_json
end

Then /^I should receive the following JSON object response:$/ do |expected_json|
  expected_json = JSON.parse(expected_json)
  response_json = JSON.parse(last_response.body)

  if expected_json['id'] == 'RESPONSE_ID'
    expected_json['id'] = response_json['id']
  end

  response_json.should == expected_json
end

特征:
# features/api/some_feature.feature
Feature: Users API
  Background:
    Given the following users exist:
      | id | name |
      | 1  | Joe  |
      | 2  | Sue  |
      | 3  | Paul |

  Scenario: Index action
    When I send a GET request to "/users/"
    Then the JSON response should have 3 "user" elements
    And I should receive the following JSON response:
      """
      [
        {
          "id":1,
          "name":"Joe"
        },
        {
          "id":2,
          "name":"Sue"
        },
        {
          "id":3,
          "name":"Paul"
        }
      ]
      """

  Scenario: Create action
    When I send a POST request to "/users/" with:
      """
      {
        "name":"Polly"
      }
      """
    Then I should receive the following JSON object response:
      """
      {
        "id":"RESPONSE_ID",
        "name":"Polly"
      }
      """
    And I send a GET request to "/users/"
    And the JSON response should have 4 "user" elements

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接