Search code examples
ruby-on-railscarrierwaveminitest

Rails: Minitest&Carrierwave ActionView::Template::Error: undefined method `file_name' for nil:NilClass


I am trying to write tests for an app, which uses carrierwave for image uploading. The app is working. I just startet with very simple controller tests.

When trying, for example, to test root through

test "should get root" do
  get root_path
  assert_response :success
end

I get the following error message:

ERROR PagesControllerTest#test_should_get_root (1.52s)
Minitest::UnexpectedError:         ActionView::Template::Error: undefined method  `file_name' for nil:NilClass
        app/views/pages/manifesto.html.erb:1
        test/controllers/pages_controller_test.rb:6:in `block in <class:PagesControllerTest>'

The offending view would be:

<div class="" style="background: url(<%= @hero.file_name.url(:image2000) %>) no-repeat center center; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; background-size: cover;">
</div>

I have the following related fixtures:

page_sections.yml
one:
  title: MyString
  page: MyString
  description: MyString

two:
  title: MyString
  page: MyString
  description: MyString

...


page_section_images.yml
one:
  page_section: One
  image: One

two:
  page_section: Two
  image: Two

...

images.yml
one:
  file_name: MyString
  title: MyString
  alt: MyString
  author: MyString
  copyright: MyString

two:
  file_name: MyString
  title: MyString
  alt: MyString
  author: MyString
  copyright: MyString

I understand he does not get the background image when attempting to render the view. Why is that so? What do I have to do in order to be able to test my views? I am not currently testing upload. As I said the page renders correctly, only the test throws this error.

I hope someone can help me out.

Edit / The pages_controller:

class PagesController < ApplicationController

  def manifesto
    @intro_hero = Image.joins(:page_section_images).where('page_section_images.page_section_id' => '1').order("RAND()").uniq.first
    @intro_section = PageSection.where(id: 1).select("id, description, title").first 
    @hero = Image.joins(:page_section_images).where('page_section_images.page_section_id' => '2').order("RAND()").uniq.first
    @section = PageSection.where(id: 2).select("id, description, title").first 
    ...
  end

  ...
end

In my app I have 11 pagesections, so I defined in the page_section fixture 11 entries and in the page_section_images fixture 11 entries. I am new to writing tests and setting up tests.


Solution

  • Thanks to Christos-Angelos Vasilopoulos's hint I was able to solve it. The problem related to the correct data in my fixtures.

    1. In my case some controller and models had logic related to precise entries in my database. For example something such as "where('page_section_images.page_section_id' => '2')". When writing the fixtures I had to specify the id with the integer value I needed in my code. Otherwise Minitest would write his values and those would not be accepted by my code.

    2. I had code such as this: ".order("RAND()").uniq.first". In order for it to be testable I needed at least two entries which could be ordered, randomised, etc ...

    This means the fixtures need to be written thoroughly and with the code in mind.