所以,我正在阅读的一个论点是,控制器测试应该是控制器的单元测试,而请求规范应该更多地是涉及路由器,控制器和控制器的集成测试。响应。这就是我工作的代码库中的哲学。鉴于这一点,考虑到我拥有这个控制器,这是编写这两个测试的最佳方法:
class Api::WineController < ApplicationController
def show
wine = Wine.find(params[:id])
render json: { id: wine.id, varietal: wine.varietal }, status: :ok
rescue ActiveRecord::RecordNotFound
render json: { error: { message: "Wine not found") } }, status: :bad_request
end
end
所以我的请求规范看起来像大多数人写的典型的集成控制器测试:
require 'rails_helper'
RSpec.describe "Wine API", type: :request do
describe '#get /api/wine' do
let!(:wine) { create(:wine) }
subject { get "/api/wine_invite_beta/wine_tokens/:id", params }
let(:params) {
{
id: wine.id
}
}
context "and the wine exists" do
it "returns back a JSON response of names" do
subject
expect(JSON.parse(response.body)).to eq("id" => wine.id, "varietal" => wine.varietal)
expect(response).to have_http_status(:ok)
end
end
context "and wine does not exist" do
it "returns back a JSON response of errors" do
subject
expect(JSON.parse(response.body)).to eq("error" => { "message"
....
end
end
end
end
因此请求规范使用http方法(:get是使用的方法),然后命中路由器然后命中控制器。这看起来更像是集成测试。
控制器测试应该没有路由器,只测试类及其方法,就像我测试模型一样。是对的吗?人们同意吗?这就是我写作的方式:
require 'rails_helper'
RSpec.describe Api::WinesController, type: :controller do
describe "#show" do
let(:controller_instance) { described_class.new }
subject { controller_instance.show }
before do
allow(controller_instance).to receive(:params) { params }
end
let(:params) { { id: 1} }
context "and wine token exists for user" do
let!(:wine) { create(:wine) }
it "calls render with the wine token data" do
expect(controller_instance).to receive(:render).with(
json: {
id: wine.id,
varietal: wine.varietal
},
status: :ok
)
subject
end
end
可以吗?我只是设置一个期望在控制器中调用一个方法,因为这看起来像一个命令。但这感觉不对。 render
方法看起来更像是一个查询而不是一个命令,因此我可能应该在调用render之后检查控制器的状态。有谁知道怎么做?
更一般地说,人们如何看待这种方法来制作控制器与请求规范?