[英]Request spec only first context is success
我有一个请求规范,我想测试 CRUD。
问题是我首先提出的任何请求都会成功,但随后的 rest 会失败。 (意思是,在下面的情况下, GET
会成功,但POST
会失败。如果我切换 2 个上下文块, POST
然后成功,然后GET
失败)。
失败的测试表示响应是
401 Unauthorized
。 我不确定是api_key
突然变得无效还是什么。 或者和我分配给它的角色有关系。 (我为用户分配了一个 system_admin 角色,以便能够通过cancancan
进行 CRUD)
使它全部工作的方法是,如果我将所有请求放在一个大的
it
块中(我认为这不是一个好习惯,因为它只返回 1 个通过的示例,而实际上我有超过 1 个。)
我也尝试在每个块中再次登录我的用户,但仍然发生同样的事情。
我是 RSpec 的新手,因此我们将不胜感激。 非常感谢!
require 'rails_helper'
RSpec.describe "Departments", type: :request do
user = FactoryBot.build(:user)
role = FactoryBot.build(:role, name: "system_admin")
user.add_role(role.name)
headers = { "x-app-api-key" => user.api_key }
before do
sign_in user
end
describe "CRUD /v1/departments" do
context "GET" do
it "called get" do
get api_departments_path, headers: headers
expect(response.content_type).to eq("application/json; charset=utf-8")
expect(response).to have_http_status(:success)
end
end
context "POST" do
it "called post" do
post api_departments_path, headers: headers, params: { name: "department" }
expect(response.content_type).to eq("application/json; charset=utf-8")
expect(response).to have_http_status(:success)
end
end
end
end
这个规范有很多问题。 首先是使用局部变量而不是let/let!
:
require 'rails_helper'
RSpec.describe "Departments", type: :request do
user = FactoryBot.build(:user)
role = FactoryBot.build(:role, name: "system_admin")
user.add_role(role.name)
这样做的问题是这些变量将在 RSpec 设置规范时设置,而不是为每个示例设置。 因此,如果您确实将记录插入到数据库中,则在第一个示例运行后它们仍将被擦除,并且所有后续示例都将失败。
所以让我们解决这个问题:
require 'rails_helper'
RSpec.describe "Departments", type: :request do
let(:user) { FactoryBot.create(:user) }
let(:role) { FactoryBot.create(:role, name: "system_admin") }
before do
user.add_role(role.name)
end
let
每个示例评估一次,然后记忆。
请注意使用create
而不是build
将记录保存在数据库中,以便实际上可以从 controller 访问它。
那么问题是,除了测试 http 响应代码之外,这些测试实际上不提供任何值或描述您正在测试的应用程序的行为。
测试您的应用程序 - 而不是您的测试。 如果失败消息没有告诉您有关应用程序的哪一部分不工作的任何信息,那么测试几乎毫无价值。
require 'rails_helper'
RSpec.describe "Departments", type: :request do
let(:user) { FactoryBot.create(:user) }
let(:role) { FactoryBot.create(:role, name: "system_admin") }
let(:headers) do
{ "x-app-api-key" => user.api_key }
end
let(:json) { response.parsed_body }
before do
user.add_role(role.name)
sign_in user
end
describe "GET /v1/departments" do
let(:departments) { FactoryBot.create_list(:department, 5) }
it "responds with a list of the departments" do
get api_departments_path, headers: headers
expect(response).to be_successful
# @todo ensure the JSON response contains the expected departments
end
end
describe "POST /v1/departments" do
context "with invalid parameters" do
let(:params) { { name: "" } } # this should just be an invalid or incomplete set of attributes
it "doesn't create a department" do
expect do
post api_departments_path, headers: headers, params: params
end.to_not change(Department, :count)
expect(response).to have_http_status(:unprocessable_entity)
end
end
context "with valid parameters" do
let(:params) { FactoryBot.attributes_for(:department) }
it "creates a department" do
expect do
post api_departments_path, headers: headers, params: params
end.to change(Department, :count).by(1)
expect(response).to have_http_status(:created)
# @todo test that either a JSON representation is returned
# or that the response contains a location header with the URI
# to the resource
end
end
end
end
测试内容类型在很大程度上是多余的,因为您将内容类型设置为 API 应用程序的默认值,如果不返回application/json
,则测试 JSON 响应将失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.