# Trying to Overide Class Object Methdos For Testing

**URL:** <https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045>\
**Category:** Rails\
**Created:** [August 15, 2006, 8:54pm UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045 "2006-08-15T20:54:33Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 15, 2006, 8:54pm UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/1 "2006-08-15T20:54:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 15, 2006, 10:42pm UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/2 "2006-08-15T22:42:50Z")

</div>

On 15/08/06, Steven H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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.org](http://mocha.rubyforge.org)to 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 Mead](https://jamesmead.org/)**
>
> Ruby Developer, author of Mocha, and ex-Antarctic Hero.

---

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 15, 2006, 11:45pm UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/3 "2006-08-15T23:45:57Z")

</div>

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.org](http://mocha.rubyforge.org)to write the test more concisely…
> 
> * * *
> 
> * * *
> 
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](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

---

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 15, 2006, 11:57pm UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/4 "2006-08-15T23:57:59Z")

</div>

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](http://blog.floehopper.org)  
> > > I would like to redefine a method at the class object level. Thus any
> 
> * * *
> 
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](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

---

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 16, 2006, 1:16am UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/5 "2006-08-16T01:16:06Z")

</div>

James M. wrote:

> # first definition (perhaps in another file)
> 
> class ValidationMaster
> 
> > to something like Mocha.
> 
> * * *
> 
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](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

---

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 16, 2006, 1:37am UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/6 "2006-08-16T01:37:09Z")

</div>

On 15/08/06, Steven H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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 Mead](https://jamesmead.org/)**
>
> Ruby Developer, author of Mocha, and ex-Antarctic Hero.

---

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 16, 2006, 1:46am UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/7 "2006-08-16T01:46:09Z")

</div>

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  
> > removed\_email\_address@domain.invalid  
> > [http://lists.rubyonrails.org/mailman/listinfo/rails](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

---

<div class="post-metadata">

**Author:** ![rooster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rooster](https://www.ruby-forum.com/u/rooster)\
**Post date:** [August 16, 2006, 12:34am UTC](https://www.ruby-forum.com/t/trying-to-overide-class-object-methdos-for-testing/65045/8 "2006-08-16T00:34:03Z")

</div>

On 15/08/06, Steven H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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.

> **[James Mead](https://jamesmead.org/)**
>
> Ruby Developer, author of Mocha, and ex-Antarctic Hero.
