Problem with FlexMock::TestCase#flexstub in 0.4.0

Jim,

I’m really glad to see the stubbing capabilities added to FlexMock.
However, I’m having a problem with the flexstub method.

I have several domain classes (ActiveRecord) in my application, and I
am working on functionality that will import data into the application
from a de-normalized tab-separated file we get from our customer on an
ongoing basis. Each line in the file represents a Product, so the code
calls Product.import( data_hash_from_line ) for each line in the file.
Product.import then calls the import method on several related
classes, giving each one the responsibility for knowing how to handle
its portion of the data.

For the unit tests, I’m using FlexMock to stub out the calls to import
in the other classes. If I run a single test case using ruby test/unit/my_test_file.rb, everything works as expected. However,
when I try to run the whole test suite using rake (this is a Rails
app, BTW), I start to see a lot of errors like this:

  1. Error:
    test_should_return_status_if_it_exists(StatusTest::Import):
    NoMethodError: undefined method import' for #<FlexMock:0x236a0e0> /usr/local/lib/ruby/gems/1.8/gems/flexmock-0.4.0/lib/flexmock.rb:113:in method_missing’
    /usr/local/lib/ruby/gems/1.8/gems/flexmock-0.4.0/lib/flexmock.rb:228:in
    mock_wrap' /usr/local/lib/ruby/gems/1.8/gems/flexmock-0.4.0/lib/flexmock.rb:108:in method_missing’
    (eval):3:in import' (eval):5:in import’
    /Users/jwilger/projects/application/test/test_helper.rb:70:in
    import' ./test/unit/status_test.rb:55:in test_should_return_status_if_it_exists’

It looks like the FlexMock::TestCase#flexmock_teardown method is
removing the stub for Status.import, but it isn’t restoring the
original method.


Regards,
John W.

On 9/5/06, John W. [email protected] wrote:

For the unit tests, I’m using FlexMock to stub out the calls to import
in the other classes. If I run a single test case using ruby test/unit/my_test_file.rb, everything works as expected. However,
when I try to run the whole test suite using rake (this is a Rails
app, BTW), I start to see a lot of errors like this:

  1. Error:
    test_should_return_status_if_it_exists(StatusTest::Import):
    NoMethodError: undefined method `import’ for #FlexMock:0x236a0e0

It looks like the FlexMock::TestCase#flexmock_teardown method is
removing the stub for Status.import, but it isn’t restoring the
original method.

Bad form replying to myself, I know – but I think I figured out
what’s going on…

In my tests, I’ve been been doing this:

class MyTest < Test::Unit::TestCase
include FlexMock::TestCase

def setup
  # set up a default stub
  flexstub( SomeClass ).should_receive( :foo )
end

def test_method_that_calls_foo_but_not_interested_in_foo_a
  SomeOtherClass.do_something_that_calls_foo
  # other assertions, etc
end

def test_method_that_calls_foo_but_not_interested_in_foo_b
  SomeOtherClass.do_something_that_calls_foo
  # other assertions, etc
end

def test_method_that_calls_foo_and_cares
  flexstub( SomeClass ).should_receive( :foo ).once.with( :bar )
  SomeOtherClass.do_something_that_calls_foo
end

end

So, I want to be able to set up a default stub for SomeClass.foo, so
that I can test SomeOtherClass.do_something_that_calls_foo without
using the actual implimentation of SomeClass.foo, but I don’t want to
have to write that default stub out in each test method.

The problem is that when test_method_that_calls_foo_and_cares is run,
it thinks the default stub is the original method, and when the test
is finished running, it’s the default stub method that ends up being
restored.

In order to make this work, we just need to make sure that the
original method isn’t overwritten if we make more than one call to
#should_receive for a particular stub. It’s a pretty simple change on
line 1008 of lib/flexmock.rb. Just change:

@method_definitions[method_name] = @obj.method(method_name)

to:

@method_definitions[method_name] ||= @obj.method(method_name)

All existing unit tests for the FlexMock library still pass with that
change in place (though I’ve not yet written any tests to cover this
case), and it solves the problem I was having with FlexMock in my
own application.


Regards,
John W.