预期响应为 <redirect>,但在使用 get :edit 时为 <200>



我在rspec中重定向和测试它时遇到问题

当我使用get方法时,我遇到了测试不通过的问题,但当我使用put方法时,对于相同的代码库,测试是绿色的。我不知道如何解决这个问题,需要帮助才能通过测试。

我得到了一个200 HTTP状态代码,但我想得到重定向的确认,这样它就可以被rspec跟踪。代码基本上需要做的是,当尝试用get http method编辑产品时,用flash error: 'You are not allowed to edit this product.'将不是产品所有者的登录用户重定向到category_product_url(category, product)

使用过的宝石rspec-railsdevisedecent_exposure。Ruby 2.1.5和Rails 4.1.8

实际错误消息:

Failure/Error: expect(response).to redirect_to(category_product_url(category, product))
   Expected response to be a <redirect>, but was <200>
Failure/Error: expect(controller.flash[:error]).to eq 'You are not allowed to edit this product.'
   
   expected: "You are not allowed to edit this product."
        got: nil
   
   (compared using ==)

我的规格

context 'another user is singed in' do
let(:user) { create(:user) }
let(:user2) { build(:user) }
let(:product) { Product.create! valid_attributes }
before do
  sign_in user2
  controller.stub(:user_signed_in?).and_return(true)
  controller.stub(:current_user).and_return(user2)
  controller.stub(:authenticate_user!).and_return(user2)
  product.user = user
end
describe 'GET edit' do
  describe 'with valid params' do
    it 'redirects to product page' do
      get :edit, { id: product.to_param, category_id: category.to_param }
      expect(response).to redirect_to(category_product_url(category, product))
    end
    it 'renders error message' do
      get :edit, { id: product.to_param, category_id: category.to_param }
      expect(controller.flash[:error]).to eq 'You are not allowed to edit this product.'
    end
  end
end

我的控制器

before_action :authenticate_user!, only: [:new, :edit, :update, :destroy, :create]
expose(:category)
expose(:products)
expose(:product)
def edit
end
def update
  if product.user == current_user
    if self.product.update(product_params)
      redirect_to category_product_url(category, product), notice: 'Product was successfully updated.'
    else
      render action: 'edit'
    end
  else
     redirect_to category_product_url(category, product), flash: { error: 'You are not allowed to edit this product.' } 
  end
end
private
def product_params
  params.require(:product).permit(:title, :description, :price, :category_id, :user_id)
end

奇怪的是,put方法在相同的update操作下运行良好。以下规格通过

describe 'PUT update' do
  describe 'with valid params' do
    it 'redirects to product page' do
      put :update, { id: product.to_param, product: { 'title' => 'MyString' }, category_id: category.to_param }
      expect(response).to redirect_to(category_product_url(category, product))
    end
    it 'does not update product' do
      put :update, { id: product.to_param, product: { 'title' => 'MyNewString' }, category_id: category.to_param }
      expect(controller.product.title).to_not eq 'MyNewString'
    end
    it 'renders error message' do
      put :update, { id: product.to_param, product: { 'title' => 'MyString' }, category_id: category.to_param }
      expect(controller.flash[:error]).to eq 'You are not allowed to edit this product.'
    end
  end
end

decent_exposuredevise的工作方式是,您需要首先调用一个before_action方法,将您选择的私有方法传递给它。

对于这个特定的例子,你的控制器应该包含这个

before_action :author!, only: [:edit, :update]

和专用方法过滤器

def author!
  unless self.product.user == current_user
    redirect_to category_product_url(category, product),
      flash: { error: 'You are not allowed to edit this product.' }
  end
end

通过这种方式,您可以使get http requestsput http requests通过规格。

试试这个

expect(:get => "/products/1/edit").to route_to(:controller => "controller_name", :action => "action_name")

希望这能奏效。

最新更新