Search code examples
ruby-on-railsminitest

MiniTest Controller Updates - Expected response to be a <3XX: redirect>, but was a <200: OK>


I have some controller tests that keep failing but I don't know why. The controller update action:

  def update
    respond_to do |format|
      if @tag_category.update(tag_category_params)
        format.html { redirect_to company_tags_url, notice: 'Tag category was successfully updated.' }
      else
        format.html { render :edit }
      end
    end
  end

and corresponding test:

  test "should update tag_category" do
    patch company_tag_category_url(@tag_category), params: { ... }
    assert_redirected_to company_tags_url
  end

the test fails (same issue in other controller also:

 FAIL["test_should_update_tag_category", #<Minitest::Reporters::Suite:0x00007f973befd100 @name="TagCategoriesControllerTest">, 62.38744100002805]
 test_should_update_tag_category#TagCategoriesControllerTest (62.39s)
        Expected response to be a <3XX: redirect>, but was a <200: OK>
        test/controllers/tag_categories_controller_test.rb:44:in `block in <class:TagCategoriesControllerTest>'

My create action has the exact same redirect logic but the test is like this:

  test "should create tag_category" do
    assert_difference('TagCategory.count') do
      post company_tag_categories_url, params: { ... }
    end
    assert_redirected_to company_tags_url
  end

I seem to be missing something obvious here. I tried follow_redirect! but that didn't work. The assert is seeing the patch return 200 NOT the redirect that follows.

UPDATE FOR THE BOUNTY

Finding this in other tests - this one works fine (both redirect in the browser and can see the redirect in the logs):

Controller:

  # PATCH/PUT /wbs/1
  def update
    authorize @wbs
    if @wbs.update(wbs_params)
      redirect_to @wbs, notice: 'Work breakdown structure was successfully updated.'
    else
      render :edit
    end
  end

Test:

  test "should update work_breakdown_structure" do
    patch work_breakdown_structure_url(@work_breakdown_structure), params: { work_breakdown_structure: { description: @work_breakdown_structure.description } }
    assert_redirected_to work_breakdown_structure_url(@work_breakdown_structure)
  end

This one fails:

Controller:

  # PATCH/PUT /wells/1
  def update
    authorize @well
    if @well.update(well_params)
      redirect_to @well, notice: 'Well was successfully updated.'
    else
      render :edit
    end
  end

Test:

  test "should update well" do
    patch well_url(@well), params: { well: { description: @well.description } }
    assert_redirected_to well_url(@well)
  end

Solution

  • Inside your controller method, you have a control flow which checks if the @tag_category instance was successfully updated. In case it is, it redirects to company_tags_url. In case it's not, it renders the :edit view.

    My guess is that the model is not getting updated and the controller is responding with the condition under the else block (rails will respond with a 200 when executing render).

    Instead of rendering the edit view, try redirecting the user to edit_company_tag_path(@tag_category) , and if that's the case your test will fail not because it was expecting a 3XX response, but because it was redirected to the wrong page.