I''m trying to test a controller method''s error handling. To do so I need to mock out a method that normally returns a unique number so that it returns a duplicate number several times in a row thereby triggering the error handling. However, I can''t get the mock working. Here''s the test code along with the error (all from test/functional/ storage_api_test.rb). class StorageController @mock_uuid = ["7cd00940-df96-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4"] def get_next_uuid @mock_uuid.shift end end class StorageControllerApiTest < Test::Unit::TestCase [big snip of standard stuff] def test_assign_uuid a = @controller.get_next_uuid # fails before assertion end end cremes$ ruby test/functional/storage_api_test.rb -n test_assign_uuid Loaded suite test/functional/storage_api_test Started E Finished in 0.074318 seconds. 1) Error: test_assign_uuid(StorageControllerApiTest): NoMethodError: You have a nil object when you didn''t expect it! You might have expected an instance of Array. The error occured while evaluating nil.shift test/functional/storage_api_test.rb:16:in `get_next_uuid'' test/functional/storage_api_test.rb:275:in `test_assign_uuid'' 1 tests, 0 assertions, 0 failures, 1 errors (BTW, I understand that this functionality should probably live in one of the models used by this controller. I plan to move it there during my next refactoring session.) I thought I was doing this correctly by reopening my StorageController class and redefining the #get_next_uuid method. What am I doing wrong and how should I fix it? cr
On Jun 16, 2006, at 12:17 PM, cremes.devlist@mac.com wrote:> I''m trying to test a controller method''s error handling. To do so I > need to mock out a method that normally returns a unique number so > that it returns a duplicate number several times in a row thereby > triggering the error handling. However, I can''t get the mock > working. Here''s the test code along with the error (all from test/ > functional/storage_api_test.rb). > > class StorageController > @mock_uuid = ["7cd00940-df96-0128-85c8-000a95ba12c4", > "cca3c300-df8f-0128-85c8-000a95ba12c4", > "cca3c300-df8f-0128-85c8-000a95ba12c4", > "cca3c300-df8f-0128-85c8-000a95ba12c4", > "cca3c300-df8f-0128-85c8-000a95ba12c4"]> 1 tests, 0 assertions, 0 failures, 1 errors > > (BTW, I understand that this functionality should probably live in > one of the models used by this controller. I plan to move it there > during my next refactoring session.) > > I thought I was doing this correctly by reopening my > StorageController class and redefining the #get_next_uuid method. > What am I doing wrong and how should I fix it? > > crHey The problem you are having is a scope issue. When you are setting @mock_uuid outside of a method, you are creating an instance variable on the class object itself and not the instance. So put your declaration in a before filter instead and you will be fine: class StorageController before_filter :setup_uuid def setup_uuid @mock_uuid = ["7cd00940-df96-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4"] end protected :setup_uuid #other coded end Cheers- -Ezra
On Jun 16, 2006, at 2:46 PM, Ezra Zygmuntowicz wrote:> > On Jun 16, 2006, at 12:17 PM, cremes.devlist@mac.com wrote: > >> I''m trying to test a controller method''s error handling. To do so >> I need to mock out a method that normally returns a unique number >> so that it returns a duplicate number several times in a row >> thereby triggering the error handling. However, I can''t get the >> mock working. Here''s the test code along with the error (all from >> test/functional/storage_api_test.rb). >> [snip] >> cr > > Hey > > The problem you are having is a scope issue. When you are setting > @mock_uuid outside of a method, you are creating an instance > variable on the class object itself and not the instance. So put > your declaration in a before filter instead and you will be fine: > > [snip code]I tried this and I still get the same error. 1) Error: test_assign_uuid(StorageControllerApiTest): NoMethodError: You have a nil object when you didn''t expect it! You might have expected an instance of Array. The error occured while evaluating nil.shift /Volumes/spaceman/cremes/developer/projects/ruby/rails/rogilefs/ config/../test/mocks/test/storage_controller.rb:16:in `get_next_uuid'' test/functional/storage_api_test.rb:284:in `test_assign_uuid'' The exact code is: require ''controllers/storage_controller'' class StorageController before_filter :setup_uuid def setup_uuid @mock_uuid = ["7cd00940-df96-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4", "cca3c300-df8f-0128-85c8-000a95ba12c4"] end protected :setup_uuid def get_next_uuid @mock_uuid.shift end end And back in the actual functional test itself... def test_assign_uuid a = @controller.get_next_uuid end I also have flexmock installed and made a (separate) attempt to use it to replace the UUID object that creates these values. Unfortunately I can''t seem to mock a class that has no instance methods; they are all class methods (e.g. UUID.new returns a string instead of a uuid instance object.) If I could figure out how to mock that object (the gem uuid) then I could eliminate mocking out this method call. I would actually prefer to do it this way since I have other tests that, as a side effect, call #get_next_uuid and I would prefer those calls to be through the real method and not the mocked one. Thanks for any further help. cr