我为控制器创建了一组规格(Photo),它是用户的嵌套资源。 规范全部通过但是当我在照片控制器中引入CanCan时,其中一些失败了:
load_and_authorize_resource :user
load_and_authorize_resource :photo
以下是我的一个规范中的失败测试用例:
describe "get 'show'" do
let(:photo) { Factory.stub(:photo) }
it "searches for the users photo" do
@user.photos.should_receive(:find).with(:photo.object_id);
get :show, :user_id => @user.id, :id => :photo.object_id;
end
context "when the photo doesn't exist" do
before do
@user.photos.stub(:find).with(:photo.object_id).and_raise(ActiveRecord::RecordNotFound);
get :show, :user_id => @user.id, :id => :photo.object_id;
end
it "assigns photo to nil" do
assigns[:photo].should be_nil;
end
it "renders the '404' template" do
response.status.should eql 404;
response.should render_template("#{Rails.root.to_s}/public/404.html") end
end
end
...
end
我已将用户设置在spec文件的顶部:
login(:user)
before do
@user = controller.current_user # this could be any user.
User.stub!(:find).and_return(@user)
end
并且Photos控制器中的show方法如下所示:
def show
# @user = User.find(params[:user_id])
# @photo = @user.photos.find(params[:id])
end
请注意,该操作为空,因为Cancan会自动执行所需的查找。在我介绍Cancan之前,行动中的两行没有被注释掉。
在我的测试中,例如,当我测试在用户照片上调用find方法时,测试失败。 Cancan必须使用其他技术来查找用户照片(@ users.photos.find()除外)。有谁知道如何为用户Cancan的控制器重写上述测试,即用可以工作的东西替换查找存根?
我正在寻找的理想情况是使用Cancan的RESTful控制器的一些示例规范。即使是节目动作的规范也很有用。
感谢阅读!
埃迪
ps - 我正在使用Rails 3.0.6,Cancan 1.6.4和Devise 1.3.3
答案 0 :(得分:2)
这有一个技术术语,但测试中存在风格差异,您可以编写定义实现的测试,定义结果的测试。
这样的代码:
@user.photos.should_receive(:find).with(:photo.object_id);
声明应该获取照片的方式是在照片关联上使用查找操作。由于这不是cancan加载照片对象的方式,这会导致测试中出现问题。
另一种方法是定义所需的结果,并在测试中保持实现未定义。这使得测试不那么脆弱,并为代码重构提供了更多机会。
assigns[:photo].should eq photo;
这种方法的缺点是它需要使用工厂(Factory.create
)而不是Fixtures(Factory.stub
),但在我看来,更灵活的测试风格证明了它的合理性。
答案 1 :(得分:0)
答案是:Rspec, CanCan and Devise,但我不确定是否要修补CanCan。我更愿意理解并以正确的方式指出模拟。我知道关键问题是CanCan不会调用Contact.new(params [:contact])。相反,它在根据当前能力权限应用了一些初始属性后,稍后调用contact.attributes = params [:contact]。如何解决这个问题?这就是我现在正在做的事情。