stevehodgkiss/generator_spec

How to test generators that invoke other generators?

murphyslaw opened this issue · 5 comments

Hello,

I have the situation, that my generator invokes another generator. Kind of like the Rails scaffold generator. When I test the generator and define the destination then only the generator under test respects this path, but the invoked generator places its file in my top level application tree.

How can I tell the other generator classes to use the destination I configured in the test case?

I have found a way, but I'm not sure if it's the best way to go...

I created a module to patch the invoked generators:

# File: spec/support/test_destination_root.rb

module TestDestinationRoot
  def initialize(*args)
    super(*args)

    self.destination_root = File.expand_path('../../../tmp', __FILE__)
  end
end

Then I required the file in the spec_helper:

# File: spec/spec_helper.rb

require 'support/test_destination_root'

And now I can patch the invoked generators in the generator spec files, where needed:

# File: spec/generators/my_generator_spec.rb

require 'spec_helper'

require 'generator_spec/test_case'
require 'rails/generators/test_case'

require 'generators/my_generator.rb'
require 'generators/my_invoked_generator'

describe MyGenerator do
  include GeneratorSpec::TestCase

  destination File.expand_path('../../../tmp', __FILE__)

  before(:all) do
    MyInvokedGenerator.send(:include, TestDestinationRoot)
  end

This scenario would also allow me to add the before(:all) block in the rspec configuration, to patch all generators all the time, but not all of my tests need that, so I thought I do it based on the test case.

Any better solution or idea, then to monkey patch the initializer?

@stevehodgkiss what do you think, is this the best workaround?

simi commented

What about to test only one generator per spec and use rspec-mocks to ensure that another generators are invoked?

👍 @simi: isolating your tests will also help spot issues sooner.

simi commented

@parndt I think this is ready to close.