it "creates a conference" do
allow(@club).to receive(:is_admin?).and_return(true)
post "/api/v1/conferences", @conference_params, {"HTTP_API_KEYAPI_KEY" => @member.api_token}
expect(response.status).to eq(201)
end
post do
authenticate!
club = fetch_club
if club.is_admin?(current_member)
xxxxxxxx
end
end
我想 mock club.is_admin? 这个方法,但是不管用。。。。应该如何 mock?
#3 楼 @kayakjiang 恩 这个是 在 before(:each) 里面 create 出来的
before(:each) do
@club = create(:public_community)
end
试下这个 allow(instance_double(@club.class)).to receive(:is_admin?).and_return(true)
或者
allow(instance_double(@club)).to receive(:is_admin?).and_return(true)
@TsingHan
allow(@club).to receive(:is_admin?).and_return(true)
只是 stub 了一个名叫@club
的变量,它跟club = fetch_club
说的不是同一个,故而无用。
假定fetch_club
方法是Club.find
,即 club 是 Club 的一个 instance, 你可以这样 stub
Club.any_instance.stub(:is_admin?).and_return(true)
Hope these help.
#6 楼 @JIAZHEN 额 , fetch_club 方法 Club.where.first,我在测试中设置了个断点
before(:each) do
@club = create(:public_community)
@member = @club.member
end
it "creates a conference" do
Club.any_instance.stub(:is_admin?).and_return(true)
binding.pry
post "/api/v1/conferences", @conference_params, {"HTTP_API_KEYAPI_KEY" => @member.api_token}
expect(response.status).to eq(201)
end
在断点处调试 @club.is_admin?(@member.id) => false
这里直接输入 false 了,哪里不对?
#6 楼 @JIAZHEN 我把测试改了一下,在测试中分别 mock fetch_club, @club.is_admin? 但是 if @club.is_admin?还是返回 false, controller.stub(:fetch_club).and_return(@club) 这种 mock 对吗?
it "creates a conference" do
@club.stub(:is_admin?).and_return(true)
controller.stub(:fetch_club).and_return(@club)
post "/api/v1/conferences", @conference_params, {"HTTP_API_KEYAPI_KEY" => @member.api_token}
expect(response.status).to eq(201)
end
api 代码也同时改了
post do
authenticate!
@club = fetch_club
if @club.is_admin?(current_member.id)
xxxxxx
end
end
额 mock 出来了,问题就是在测试中 mock 的 club 和 api 代码中不是同一个实例 fetch_club 方法是定义在 grape helper 里面 所以就 mock fetch_club https://github.com/intridea/grape#stubbing-helpers 这样 就 ok 了,谢谢帮忙回答问题的几位~~~
before do
Grape::Endpoint.before_each do |endpoint|
endpoint.stub(:fetch_club).and_return(@club)
end
end
it "creates a conference" do
@club.stub(:is_admin?).and_return(true)
post "/api/v1/conferences", @conference_params, {"HTTP_API_KEYAPI_KEY" => @member.api_token}
expect(response.status).to eq(201)
end
#7 楼 @TsingHan
@user
生成于你 stub 之前,所以你此时不成功。
before do
Club.any_instance.stub(:is_admin?).and_return(true)
@club = create(:public_community)
@member = @club.member
end
it "creates a conference" do
post "/api/v1/conferences", @conference_params, {"HTTP_API_KEYAPI_KEY" => @member.api_token}
expect(response.status).to eq(201)
end
应该就可以了
#12 楼 @JIAZHEN 我按照你上面的写法试了试,我感觉 Club.any_instance.stub(:is_admin?).and_return(true) 这种写法应该可以,但返回的还不是 mock 的 true。
我的程序代码是这么写的
@club = fetch_club
if @club.is_admin?(current_member.id)
xxxxx
end
我感觉是因为 fetch_club(写在 grape 的 helper 里) 这块的问题?我上面是用下面这种方式来 mock fetch_club,这样就正常
Grape::Endpoint.before_each do |endpoint|
endpoint.stub(:fetch_club).and_return(@club)
end
@TsingHan Sorry for the delay. 今天刚刚看到。
Ahh, 原因是在fetch_club
方法。它不是直接查询数据库或者直接使用 Club Object. 而是用 Grape 调用一个 api call。所以你应该 mock 的是Grape::Endpoint
. 这里的信息 miss 了。
你用 mock 的时候,应该想清楚到底要 mock 哪个 object. 另外,RSpec 支持 verify_double
, 完善了以前double
的一个漏洞。FYI - http://relishapp.com/rspec/rspec-mocks/docs/verifying-doubles