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.
- 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, [email protected] wrote:
"cca3c300-df8f-0128-85c8-000a95ba12c4",
"cca3c300-df8f-0128-85c8-000a95ba12c4",
"cca3c300-df8f-0128-85c8-000a95ba12c4"]
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:
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 Z. wrote:
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.
- 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