我是测试和学习Rspec的新手,而且我无法开始工作。
(我已经阅读了“使用Rspec3进行有效测试,以及许多教程......还有pluralsight.com”这本书)
情况很简单。在Companies
控制器中,我想测试de Create方法,company
模型belongs_to user
,这就是代码:
我认为问题出在执行时
测试中的:expect(Company).to receive(:new).with(company_params)
或在控制器中:@company.user=helpers.user
控制器:
class CompaniesController < SessionsController
def create
@company=Company.new(company_params)
@company.user=helpers.user
if @company.save()
redirect_to companies_path
else
render :edit
end
end
和Rspec:
RSpec.describe CompaniesController, type: :controller do
let(:user) { instance_double(User) }
before do
allow_any_instance_of(ApplicationHelper).to receive(:user){user}
allow(controller).to receive(:authorize){true}
end
describe 'Authenticated user with companies' do
let(:company_params) { {company:{name:"Albert",domain:"www.albert.com"}} }
let(:company) { instance_double(Company) }
before do
allow(Company).to receive(:new){company}
end
describe 'POST #create' do
context "with valid data" do
before { allow(company).to receive(:save){true} }
it "redirects to companies_path" do
expect(Company).to receive(:new).with(company_params)
expect(company).to receive(:user=).with(user)
post :create, params:{company: company_params}
expect(response).to redirect_to(companies_path)
end
我的意图非常简单:使用instance_double模拟(或存根)@company和Company.new,使用实例double ...来测试创建操作,并模拟&#34; save()&#34 ;回归真......等等。
我不知道我是否能很好地解释自己,但考虑到控制器的create
动作,如何使用mocks和stub来测试,instance_double?
由于
答案 0 :(得分:1)
首先让我解释一下我们需要在这里测试什么
def create
@company=Company.new(company_params)
@company.user=helpers.user
if @company.save()
redirect_to companies_path
else
render :edit
end
end
我们正在测试控制器的create
动作。首先让我们看一下这个动作的作用?它只需要comapany_params
作为输入并在数据库中创建公司记录。
测试也是如此,我们需要传递所需的操作输入,并且需要检查它是否在数据库中创建记录。
RSpec.describe CompaniesController, type: :controller do
let(:user) { instance_double(User) }
before do
# all your authentication stubing goes here
allow_any_instance_of(ApplicationHelper).to receive(:user){user}
allow(controller).to receive(:authorize){true}
end
describe 'POST#create' do
context 'with valid attributes' do
before do
post :create, { company:{ name:"Albert", domain:"www.albert.com"} }
end
it 'responds with success' do
expect(response.status).to eq(302)
end
it 'creates company' do
company = Company.find_by(name: "Albert")
expect(assigns(:company)).to eq(company)
expect(response).to redirect_to(companies_path())
end
end
context 'with invalid attributes' do
before do
post :create, { company:{ name:"", domain:""} }
end
it 'renders new template' do
expect(response).to render_template(:edit)
end
end
end
end
这里不需要任何东西。据我所知,只有当我们在操作中使用任何lib classes
/ background jobs
/ third party libraries
代码时,我们才需要存根这些代码。因为对于所有这些,我们将分别编写规范。因此,无需再次测试我们为什么要进行存根。
答案 1 :(得分:0)
感谢Narsimha Reddy,我对如何测试有更好的想法。 尽管如此,如果我想要存根
@company=Company.new(company_params)
@company.user=helpers.user
if @company.save()
仅测试de create
的响应,解决方案充分利用了参数,并允许allow(company).to receive(:user=)
用于belongs_to关联
let(:company_params) {{company:{name:"Albert",domain:"www.albert.com"}}}
let(:ac_company_params) {ActionController::Parameters.new(company_params).require(:company).permit!}
let(:company) { instance_double(Company) }
before do
allow(Company).to receive(:new){company}
allow(company).to receive(:user=)
allow(company).to receive(:save){true}
end
it "redirects to companies_path" do
expect(Company).to receive(:new).with(ac_company_params)
expect(company).to receive(:user=).with(user)
post :create, params: company_params
expect(response).to redirect_to(companies_path)
end