From: Paul J. <pau...@me...> - 2002-06-28 05:02:50
|
The approach we have been taking is to extend a Factory with a = MockFactory have a static Factory.setInstance(Factory f) that allows us = to setup the MockFactory as the real factory. That is assuming that we use a singleton pattern to return the Factory = (or MockFactory) with the static Factory.instance() method. Is this the best approach or is there a better one? For example, the code would look like this... public class Factory { private Factory factory =3D null; public static instance() { if (factory =3D=3D null) { factory =3D new Factory(); } return factory; } public static setInstance(Factory pFactory) { factory =3D pFactory; } public Bean getBean() { return new Bean(); } } public class MockFactory extends Factory { public Bean getBean() { return new MockBean(); } } Paul Jackson Meridian Informatics Phone: (02) 8233 7564 Mobile: 0418 855 496 -----Original Message----- From: moc...@li... [mailto:moc...@li...]On Behalf Of Olaf Kock Sent: Friday, 28 June 2002 3:43 AM To: Moc...@li... Subject: Re: [Mockobjects-java-users] MockObjects and Factories best practices Hi John, John Sisk wrote: >=20 > Hi there, >=20 > What is the best practice for integrating mocks into a project?=20 The key point is to shift object creation from classes to be tested to somewhere outside. That doesn't necessarily meen a factory to be involved, but the class in question will be parameterized with their collaborators from somewhere outside (probably/sometimes in the constructor). This way production code constructs objects and parameterizes them with "real" collaborators (and may do so with the use of factories or builders). Testcode on the other hand directly creates objects under test and parameterizes them with MockObjects suiting its particular needs. Don't pollute factories with mockobjects. (That is - if you wanted to ask that and I understood correctly). Production code should be able to be delivered without any MockObject. Hope that helps? Olaf --=20 abstrakt gmbh, Behringstrasse 16b, 22765 Hamburg=20 Tel: +49-40-39804630, Fax: +49-40-39804639 http://www.abstrakt.de/ |
From: Olaf K. <ok...@ab...> - 2002-06-28 07:29:57
|
Paul Jackson wrote: > > The approach we have been taking is to extend a Factory with a MockFactory have a static Factory.setInstance(Factory f) that allows us to setup the MockFactory as the real factory. > > That is assuming that we use a singleton pattern to return the Factory (or MockFactory) with the static Factory.instance() method. > > Is this the best approach or is there a better one? It's a valid approach, if there is a better one depends upon your needs. I personally prefer "building" fully configured Objects rather than leaving configuration to them - thus needing factory singletons to callback to the environment. After all, singletons are the object oriented globals. Sorry, I don't have the reference to "Singletons Are Evil" at hand. Probably somebody else could jump in. If you build configured objects, a builder (or anything else constructing them - I'm not necessarily talking exclusively about the GOF-Builder here) can configure an object one way, the testcode will configure them differently. This way testcode doesn't need to bother with factories, messing up singletons with the need for cleanups later and unpredictable side effects, if this cleanup is forgotten. Olaf -- abstrakt gmbh, Behringstrasse 16b, 22765 Hamburg Tel: +49-40-39804630, Fax: +49-40-39804639 http://www.abstrakt.de/ |
From: Steve F. <st...@m3...> - 2002-06-29 16:02:55
|
One of the points of the original paper is that the need to substitute mock implementations pushes you to pass objects around a lot more than most of us have been used to -- a "compositional" style of programming. This can force you into having lots of parameters in a signature, but that's usually a sign that there's an intermediate object waiting for you to group some behaviour together. Sometimes this means passing in factories when constructing an object, and the one concession to testing we sometimes make is to have two constructors: one which allows you to set various instance fields (so you can substitute some mocks), and one which sets up those fields with default implementations, e.g. class ThingDoer { private FooFactory fooFactory; public ThingDoer(FooFactory aFooFactory) { fooFactory = aFooFactory; } public ThingDoer() { this(new HttpFooFactory()); } - - - - Concerning the original question, I'm currently doing quite a lot of test retrofitting. One of the tricks for dealing with singletons is to declare an interface, attach it to the singleton object, and pass it in to the calling object. e.g. class Notifier {... class ThingDoer { public void makeItSo() { doStuff(); Notifier.tellTheWorld("we did it"); } } becomes class AsynchNotifier implements Notifier {... class ThingDoer { private Notifier notifier; public ThingDoer(Notifier aNotifier) { notifier = aNotifier; } public void makeItSo() { doStuff(); notifier.tellTheWorld("we did it"); } // or, alternatively public void makeItSo(Notifier notifier) { doStuff(); notifier.tellTheWorld("we did it"); } You can now test the use of the notifier by passing a mock implementation somewhere and, quite often, it turns out that it shouldn't have been a singleton after all. b.t.w., there's a SingletonsAreEvil page on the C2 wiki. Steve |