Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NoMethodError <fixture name> in Rails and minitest/spec

Without minitest/spec, the test looks like this, and the my_engine_customers fixtures are loaded (all is well):

my_engine/test/models/my_engine/customer_test.rb is

require 'test_helper'

module MyEngine
  class CustomerTest < ActiveSupport::TestCase

    test "alex is id 5" do
      assert my_engine_customers(:alex).id, 5
    end

  end
end

After adding require 'minitest/autorun' to test/test_helper.rb, and then converting the above test :

require 'test_helper'

describe MyEngine::Customer do

  let(:alex) { my_engine_customers(:alex) } # error here (error shown below)

  it "alex is id 5" do
    assert alex.id, 5
  end

end

I get this error:

NoMethodError: undefined method `my_engine_customers' for
#<#<Class:0x007fb63e8f09e8>:0x007fb63e81b068>

How do I access fixtures when using minitest/spec ?

like image 802
Zabba Avatar asked Jan 11 '15 03:01

Zabba


1 Answers

When you use the spec DSL you get a Minitest::Spec object to run your tests. But the Rails fixtures and database transaction are only available in ActiveSupport::TestCase, or test classes that inherit from it like ActionController::TestCase. So what you need is some way for the spec DSL to use ActionSupport::TestCase for you tests.

There are two steps to this, first ActiveSupport::TestCase needs to support the spec DSL. You can do this by adding the following code to you test_helper.rb file:

class ActiveSupport::TestCase
  # Add spec DSL
  extend Minitest::Spec::DSL
end

(Did you know ActiveSupport::TestCase.describe exists? You probably want to remove that method before you add the spec DSL if you plan on doing nested describes.)

Second, you need to tell the spec DSL to use ActiveSupport::TestCase. The spec DSL adds register_spec_type for just this purpose. So also add the following to your test_helper.rb file:

class ActiveSupport::TestCase
  # Use AS::TestCase for the base class when describing a model
  register_spec_type(self) do |desc|
    desc < ActiveRecord::Base if desc.is_a?(Class)
  end
end

This will look at the subject of the describe and if it is an ActiveRecord model it will use ActiveSupport::TestCase instead of Minitest::Spec to run the tests.

As you might expect, there are lots of other gotchas involved when you try to use the spec DSL for controllers and other types of tests. The easiest way IMO is to add a dependency on minitest-rails and then require "minitest/rails" in your test_helper.rb file. minitest-rails does all this configuration and more and makes the process much smoother. (Again, IMO.)

For more info see my blaurgh post Adding Minitest Spec in Rails 4. </shameless-self-promotion>

like image 168
blowmage Avatar answered Oct 11 '22 04:10

blowmage