aspose file tools*
The moose likes Agile and Other Processes and the fly likes Mock Objects Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » Agile and Other Processes
Bookmark "Mock Objects" Watch "Mock Objects" New topic
Author

Mock Objects

Matthew Phillips
Ranch Hand

Joined: Mar 09, 2001
Posts: 2676
This is probably more on topic in the testing forum, but since it is related to this weeks giveaway I'll post it here.
I am just starting to learn mock objects so that I can write a test for some code I may need to refactor. It involved the Javamail API and I want to test it without an email server.
The relevent classes are instantiated inside the method, so I can't pass mock objects in as parameters. What I am thinking about doing is using wrappers, with the appropriate package and class names, around the mock objects and having those in the class path.
Is that the appropriate way to use mock objects in this instance?


Matthew Phillips
Eric Burke
Greenhorn

Joined: May 12, 2003
Posts: 7
Originally posted by Matthew Phillips:
The relevent classes are instantiated inside the method, so I can't pass mock objects in as parameters. What I am thinking about doing is using wrappers, with the appropriate package and class names, around the mock objects and having those in the class path.
Is that the appropriate way to use mock objects in this instance?

As a last resort, that would work. But I'd really think hard about re-designing the method to accept parameters that you can easily mock out.
This is a great aspect of testing - it often forces you to improve your design in order to make it easily testable.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Eric Burke:
But I'd really think hard about re-designing the method to accept parameters that you can easily mock out.

An alternative approach would be to use a Factory to instantiate the objects. Use the "real" factory by default and provide a method to set a different Factory.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Brian Coyner
Greenhorn

Joined: Mar 22, 2003
Posts: 7
Originally posted by Ilja Preuss:

An alternative approach would be to use a Factory to instantiate the objects. Use the "real" factory by default and provide a method to set a different Factory.

The first question to ask yourself before implementing the factory pattern is, "Do I need a factory?" Using a factory to help write a test is, in my opinion, not the best solution. It should work, but it might be totally overkill and add more complexity. Of course, you may determine that a factory is exactly what you need, and if so, great! I think decoupling your code into testable modules is a cleaner approach.


Author of <a href="http://www.amazon.com/exec/obidos/ASIN/0596003870/ref=jranch-20" target="_blank" rel="nofollow">Java Extreme Programming Cookbook</a>
Matthew Phillips
Ranch Hand

Joined: Mar 09, 2001
Posts: 2676
Originally posted by Eric Burke:

As a last resort, that would work. But I'd really think hard about re-designing the method to accept parameters that you can easily mock out.
This is a great aspect of testing - it often forces you to improve your design in order to make it easily testable.

Ultimately, I want to refactor the method into what I believe is a better design, but I want to have some solid tests before starting that. Ultimately, it may be better to throw what I have away and start over, but I wanted to look at all avenues before doing that.
Thanks for the input, everyone. Keep it coming.
[ May 15, 2003: Message edited by: Matthew Phillips ]
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Brian Coyner:
I think decoupling your code into testable modules is a cleaner approach.

How is the Abstract Factory approach *not* decoupling the code into testable modules?
Matthew X. Brown
Ranch Hand

Joined: Nov 08, 2000
Posts: 165
Factory won't solve his problem. Since his ObjectToTest directly instantiate the classes needed to be mocked(ie. they are strong typed)- factories won't make a difference. His issue is access.
The only way you could get access to test is possibly using AspectJ- via a crosspoint. Checkout Nicholas Lesiecki's article - http://www-106.ibm.com/developerworks/java/library/j-aspectj2/?open&l=007,t=gr
AspectJ does have a learning curve, so unless you already know it- I would spend my time refactoring the code. However Nicholas Lesiecki is confronting the problem you are having directly- he doesn't want to change existing code to accomodate testing.
Regarding refactoring- My 2cents on that is to consider making your API's accessible via Interfaces- passing in mock objects directly via Smart Handler is good- doing it with an Interface Structure in place will even be better, if not easier.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Matthew Brown:
Factory won't solve his problem. Since his ObjectToTest directly instantiate the classes needed to be mocked(ie. they are strong typed)- factories won't make a difference. His issue is access.

Sorry, obviously I didn't make myself clear.
What I wanted to offer as an alternative approach was
- letting his ObjectToTest instantiate the classes through a Factory, and
- let the tests replace the default factory used by ObjectToTest by a MockFactory
So, instead of changing the API to let the method under test accept another parameter (which production clients also needed to do), add another method for exchanging the factory (no changes to production clients, which would transparently use the default factory).
What do you think?
Matthew X. Brown
Ranch Hand

Joined: Nov 08, 2000
Posts: 165
I would say that you do factories within the ObjectToTest class- but I was "projecting" that he doesn't want to change his ObjectToTest at all. If he doesn't mind changing his existing class- Factories are a good way of doing the mock objects(however the mock object implementation must call verify unto itself I'd think). I don't know how we'd get the handle to the actual mock object within the class to verify stuff.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Matthew Brown:
I don't know how we'd get the handle to the actual mock object within the class to verify stuff.

The test could ask the factory - or alternatively configure the factory with the actual mock object.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Mock Objects