• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Mock Objects

 
Ranch Hand
Posts: 2676
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Matthew Phillips
Ranch Hand
Posts: 2676
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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?
 
Ranch Hand
Posts: 165
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 165
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
The knights of nee want a shrubbery. And a tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic