Hi,
I thought I had a handle on the whole singleton class thing but now I’m
not too sure.
I have a class definition:
class ValidationMaster
def validate(params)
# complex and time consuming validation
# returns true on success, raises Exception
# on failure
end
end
Okay, so when I’m running my functional tests within rails, I want to be
able to control how the validate(params) method behaves.
So, I’ve created a ValidationMaster class definition and put it in
RAILS_ROOT/test/mocks/test/validation_master.rb
The methods I’ve defined there seem to be correctly overriding those of
the original class definition.
Now here is where I’m having problems. Within certain functional tests,
I want validate(params) to return true. Other times
I want it to fail and throw an exception. Thus, I can’t rely on the
Mock ValidationMaster class definition to take care of this.
But then I thought, HEY, within each test I can open up the singleton
class for the ValidationMaster class object. Whoo hoo,
I’m in charge now!
def test_stuff
class << ValidationMaster
def validate(params)
raise ValidationException
end
end
vm = ValidationMaster.new
vm.validate(“Jeff”)
end
But, when I run my test, the exception is not getting thrown. The
methods I’ve defined in the Mock are all working right, but it’s somehow
not seeing
the override within test_stuff. Am I mistaken here, can I not override
the class definition of ValidationMaster like this?
Thanks,
Steven
On 15/08/06, Steven H. [email protected] wrote:
# on failure
the original class definition.
def test_stuff
But, when I run my test, the exception is not getting thrown. The
methods I’ve defined in the Mock are all working right, but it’s somehow
not seeing
the override within test_stuff. Am I mistaken here, can I not override
the class definition of ValidationMaster like this?
I think this is what you want…
def test_stuff
vm = ValidationMaster.new
class << vm
def validate(params)
raise ValidationException
end
end
vm.validate(“Jeff”)
end
However, you might want to consider using Mocha
http://mocha.rubyforge.orgto write the test more concisely…
def test_stuff
vm = ValidationMaster.new
vm.stubs(:validate).raises(ValidationException)
vm.validate(“Jeff”)
end
Hope that helps.
James.
James M. wrote:
# returns true on success, raises Exception
The methods I’ve defined there seem to be correctly overriding those of
vm = ValidationMaster.new
http://mocha.rubyforge.orgto write the test more concisely…
Rails mailing list
[email protected]
http://lists.rubyonrails.org/mailman/listinfo/rails
I would like to redefine a method at the class object level. Thus any
new instances of the ValidationMaster object would have a new definition
for the validate(params) method. What you are doing is changing a
single instance of the ValidationMaster object.
Mocha looks pretty cool, however I’m still a bit new to the whole
testing thing so I’d like to get a bit better at it before moving on
to something like Mocha.
Thanks,
Steven
Steven H. wrote:
# complex and time consuming validation
I’m in charge now!
end
def test_stuff
However, you might want to consider using Mocha
http://blog.floehopper.org
I would like to redefine a method at the class object level. Thus any
Rails mailing list
[email protected]
http://lists.rubyonrails.org/mailman/listinfo/rails
Ok, I think I see where I’m going wrong here.
Doing:
class << ValidationMaster
end
allows me to add class level methods.
So if I had
class ValidationMaster
def validate()
end
end
and then I did
class << ValidationMaster
def validate()
end
end
I would essentially have two validiate() methods in the ValidationMaster
class. It would be like having this definition:
class ValidationMaster
def validate()
puts “one”
end
def self.validate()
puts “two”
end
end
vm = ValidationMaster.new
vm.validate() #=> “one”
ValidationMaster.validate() #=> “two”
-Steven
James M. wrote:
first definition (perhaps in another file)
class ValidationMaster
to something like Mocha.
Rails mailing list
[email protected]
http://lists.rubyonrails.org/mailman/listinfo/rails
Ok, this does what I was trying to accomplish:
class ValidationMaster
def validate(params)
# complex and time consuming validation
# returns true on success, raises Exception
# on failure
end
end
def test_validation_fails
ValidationMaster.class_eval { def validate(params); raise Exception;
end }
post(:download, opts)
assert_response(:redirect)
assert_equal(flash[:error], “Authentication failed: token
verification failed”)
end
def test_validation_succeeds
ValidationMaster.class_eval { def validate(params); return true; end
}
post(:download, opts)
assert_response(:success)
assert_equal(flash[:error], nil)
end
I don’t want the actual validation to run, I just want a specific result
from this method. The result I want differs between tests. Now I can
test my controller’s actions without having to have the “real”
validation() method executed. Sorry for not giving a better explanation
of what I was trying to do.
Thanks,
Steven
On 15/08/06, Steven H. [email protected] wrote:
def test_validation_succeeds
validation() method executed. Sorry for not giving a better explanation
of what I was trying to do.
That does work, but watch out for the gotcha that your method
re-definition
is not local to the test. So depending on which was the last of these to
run, the behaviour in other tests might not be what you expect. This is
one
of the benefits of Mocha, which restores the original implementation
after
each test (in a secret teardown). Your tests would become…
def test_validation_fails
ValidationMaster.any_instance.stubs(:validate).raises(Exception)
post(:download, opts)
assert_response(:redirect)
assert_equal(flash[:error], “Authentication failed: token
verification
failed”)
end
def test_validation_succeeds
ValidationMaster.any_instance.stubs(:validate).returns(true)
post(:download, opts)
assert_response(:success)
assert_equal(flash[:error], nil)
end
James.
James M. wrote:
end
test my controller’s actions without having to have the “real”
def test_validation_fails
assert_response(:success)
Rails mailing list
[email protected]
http://lists.rubyonrails.org/mailman/listinfo/rails
“That does work, but watch out for the gotcha that your method
re-definition is not local to the test.”
Heh, I was just about to email the list again asking about this.
“This is one of the benefits of Mocha, which restores the original
implementation after each test (in a secret teardown).”
I might using Mocha sooner than I expected.
Thanks,
Steven
On 15/08/06, Steven H. [email protected] wrote:
I would like to redefine a method at the class object level. Thus any
new instances of the ValidationMaster object would have a new definition
for the validate(params) method. What you are doing is changing a
single instance of the ValidationMaster object.
You can just re-open the class and redefine the method…
first definition (perhaps in another file)
class ValidationMaster
def validate()
puts “one”
end
end
vm = ValidationMaster.new
vm.validate # => “one”
second definition
class ValidationMaster
def validate()
puts “two”
end
end
vm = ValidationMaster.new
vm.validate # => “two”
Mocha looks pretty cool, however I’m still a bit new to the whole
testing thing so I’d like to get a bit better at it before moving on
to something like Mocha.
No worries.
James.