My application uses a third party jar (no access to source, etc.) I have a factory that creates an object (call it Foo) correctly from settings, i.e.
public FooFactoryImpl implements FooFactory {
private final Settings settings;
private final OtherDependency other;
#Inject
public FooFactoryImpl(Settings settings, OtherDependency other) {
this.settings = settings;
this.other = other;
}
public Foo create(String theirArg) {
Foo newFoo = new Foo(theirArg); // there is no no-arg constructor
// This isn't exactly the way I do it but this is shorter and close enough
newFoo.setParamOne(settings.get("ParamOne"));
newFoo.setParamTwo(settings.get("ParamTwo"));
// etc.
}
}
I would like to unit test this factory using Mockito - make sure the created object is configured correctly. But of course, I run into this problem; that is, because my factory calls new, I can't inject a spy.
One possible solution is to introduce something like:
public FooFactoryDumb implements FooFactory {
public Foo create(String theirArg) {
return new Foo(theirArg);
}
}
And then something like:
public FooFactoryImpl implements FooFactory {
#Inject #Dumb private FooFactory inner;
// snip, see above
public create(String theirArg) {
Foo newFoo = inner.create(theirArg);
// etc.
}
}
This seems like a lot of boilerplate code just to enable unit testing. It smells bad to me, but I might be wrong. Is there a better way?
There is a similar but simpler way to do it: add a protected method to your factory to create a Foo:
protected Foo create(String theirArg){
return new Foo(theirArg);
}
then in your tests of your Factory, create a Test Double of your FactoryImpl and override the create method:
private class FooFactoryImplTestDouble extends FooFactoryImpl{
...
#Override
protected Foo create(String theirArg){
//create and return your spy here
}
}
Create a new class:
public class FooFactory3rd {
public Foo create3rdParty(String theirArg) {
return new Foo(theirArg);
}
}
Then change your class to:
public FooFactoryImpl implements FooFactory {
private final Settings settings;
private final OtherDependency other;
private final FooFactory3rd fooFactory3rd;
#Inject
public FooFactoryImpl(Settings settings, OtherDependency other, FooFactory3rd fooFactory3rd) {
this.settings = settings;
this.other = other;
this.fooFactory3rd = fooFactory3rd;
}
public Foo create(String theirArg) {
Foo newFoo = fooFactory3rd.create3rdParty(theirArg);
// This isn't exactly the way I do it but this is shorter and close enough
newFoo.setParamOne(settings.get("ParamOne"));
newFoo.setParamTwo(settings.get("ParamTwo"));
// etc.
}
}
And in your test code:
Foo fooMock = mock(Foo.class);
FooFactory3rd fooFactory3rdMock = mock(FooFactory3rd.class);
when(fooFactory3rdMock.create3rdParty(any(String.class)).thenReturn(fooMock);
FooFactoryImpl fooFactoryImpl = new FooFactoryImpl(settings, other, fooFactory3rdMock);
fooFactoryImpl.create("any string");
This way, you can inject your fooMock. When you call fooFactoryImpl.create("any string"), your mocked Foo is called under the cover.
Or if you want to go further clean, don't even need the constructor arg of FooFactory3rd. Just declare
private final FooFactory3rd fooFactory3rd = new FooFactory3rd();
And in your test, use reflection to change it to the mocked FooFactory3rd.
Well, it turns out that I had to use PowerMock anyway because the third party's methods were final. Since I'm already using PowerMock, I realized I can just do this:
#Before
public void setUp() throws Exception {
Foo toReturn = PowerMockito.mock(Foo.class);
PowerMockito.whenNew(Foo.class).withAnyArguments().thenReturn(toReturn);
}
And then I don't have to touch my original class at all.
Note: If you do this, you have to prepare both classes for PowerMock, i.e. do
#PrepareForTest( { Foo.class, FooFactoryImpl.class } )
Take a step back and think about what the contract of FooFactoryImpl is. It is that it must create a fully functional Foo, whatever that means. So if the contract of a Foo is that it does X, Y and Z, then the contract of a FooFactoryImpl is that it creates objects that do X, Y and Z.
This is a case for the kind of test in which the SUT consists of more than one class. I don't care whether you call this a unit test, an integration test, a subsystem test, a collaboration test, or some other name. The point is that the only meaningful test of FooFactoryImpl is a test that tests Foo as well. Instead of writing a test class for Foo alone, write a test class that tests the two classes jointly.
So, if the contract of Foo is to do X, Y and Z, then your test cases will do the following things with a FooFactoryImpl.
Call create and test that the created object does X.
Call create and test that the created object does Y.
Call create and test that the created object does Z.
I believe this is the only sensible way to attack this problem. The hard part is coming up with a convincing name for the test class.
Related
I have the following structure of my Java code:
public MyClass {
// some class variables
...
private void process() {
private MyObject obj;
...
obj = createHelper();
...
messageHelper(obj, "One of several possible strings");
...
messageHelper(obj, "Another call with a different string");
...
}
private MyObject createHelper {
MyObject obj = new MyObject();
// some Setter calls
...
return obj;
}
private void messageHelper (MyOject obj, String message) {
...
}
}
I would like to test, that based on properties obj (that I would like to specify), messageHelper() receives the right string. In other words I need to control the result of one method and have access to the parameters of the other.
I'm still very shaky with all this Mock/Stub/Spy stuff.
It seems to me that I need to Spy on MyClass, stub CreateHelper() with a "manually" created object and not sure what for intercepting call parameters for messageHelper().
Also I noted that Wiki cautions against using Spies:
Think twice before using this feature. It might be better to change
the design of the code under specification.
So what would an appropriate Spocky way to accomplish the task?
Slightly Refactored Code: (5/5/14)
public MyClass {
// some class variables
private messageSevice = new messageService();
...
private void process() {
private MyObject obj;
...
obj = new MyObject(parameters ...);
...
if (someCondition) {
messageService.produceMessageOne(obj);
}
...
if (otherCondition) {
messageService.produceMessageTwo(obj);
{
...
}
}
public class MessageService implements IMessageService {
private final static MSG_ONE = "...";
private final static MSG_TWO = "...";
...
public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_ONE);
...
}
public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_TWO);
}
private void produceMessage(MyObject obj, String message) {
...
}
}
I would greatly appreciate if someone suggests the way it should be tested with Spock.
The caution you're referring to is rightfully there. There's a very good correlation between testable code and good design (I recommend watching this lecture from Michael Feathers to understand why http://www.youtube.com/watch?v=4cVZvoFGJTU).
Using spies tends to be a heads up for design issues since it usually arises from the impossibility of using regular mocks and stubs.
It's a little hard to predict from your example, since you're obviously using pseudo names, but it seems that the design of the MyClass class violates the single responsibility principle (http://en.wikipedia.org/wiki/Single_responsibility_principle), since it does processing, creation and messaging (3 responsibilities).
If you're willing to change your design, so that the processing class (MyClass) will do only processing, you'll be providing another class that does the creation (MyObjectFactory), and yet another class that does the messaging (MyObjectMessager) either through a constructor, setter methods or by dependency injection.
Using this new design, you can create an instance of the class you're testing (MyClass), and pass it mock objects of both the factory and messaging classes. Then you'll be able to verify whatever you want on both.
Take a look at this example (using Mockito):
public class MyClassTest {
#Test
public void testThatProcessingMessagesCorrectly() {
MyObject object = mock(MyObject.class);
MyObjectFactory factory = mock(MyObjectFactory.class);
when(factory.createMyObject()).thenReturn(object);
MyObjectMessager messager = mock(MyObjectMessager.class);
MyClass processor = new MyClass(factory, messager);
processor.process();
verify(factory).createMyObject();
verify(messager).message(EXPECTED_MESSAGE_1);
verify(messager).message(EXPECTED_MESSAGE_2);
...
verify(messager).message(EXPECTED_MESSAGE_N);
}
...
}
Here's a Spock example (untested, double check before using ...):
public class MyClassSpec extends Specification {
def "check that the right messages are produced with the expected object"() {
given:
def messageService = Mock(IMessageService)
def testedInstance = new MyClass()
testedInstance.setMessageService(messageService)
when:
testedInstance.process()
then:
1 * messageService.produceMessageOne(_)
1 * messageService.produceMessageTwo(_)
}
}
If you're a hammer, every problem is a nail
I'd like to call exception-to-the-rule here and say that sometimes stubbing private methods - necessitating spies - can be both correct and useful.
#eitanfar is most likely accurate in his analysis of the function, and 95% of the time this is the case, but as with most things - I believe - not always.
This is for those of us who believe they have an exception but get the usual "code smell" argument.
My example is a complex argument validator. Consider the following:
class Foo {
def doThing(...args) {
doThing_complexValidateArgs(args)
// do things with args
}
def private doThing_complexValidateArgs(...args) {
// ... * 20 lines of non-logic-related code that throws exceptions
}
}
Placing the validator in it's own class IMO seperates the concern too much. (a FooMethodArgumentValidator class?)
Refactoring out the validation arguably significantly improves readability of the doThing() function.
doThing_complexValidateArgs() should not be public
The doThing() function benefits from the reability of a simple call validateArgs(...) and maintains encapsulation.
All I need to be sure of now is that I have called the function within the parent one. how can I do that? well - correct me if I'm wrong - but in order to do that, I need a Spy().
class FooSpec extends Specification {
class Foo {
def doThing(...args) {
doThing_controlTest(args)
doThing_complexValidateArgs(*args)
// do things with args
}
def doThing_controlTest(args) {
// this is a test
}
def private doThing_complexValidateArgs(...args) {
// ... * 20 lines of code
}
}
void "doThing should call doThing_complexValidateArgs" () {
def fooSpy = Spy(Foo)
when:
fooSpy.doThing(1, 2, 3)
then:
1 * fooSpy.doThing_controlTest([1,2,3]) // to prove to ya'll we got into the right method
1 * fooSpy.invokeMethod('doThing_complexValidateArgs', [1, 2, 3]) // probably due to groovy weirdness, this is how we test this call
}
}
Here is my real life example I used for a static private method:
#SuppressWarnings("GroovyAccessibility")
#ConfineMetaClassChanges(DateService) // stops a global GroovySpy from affecting other tests by reseting the metaclass once done.
void "isOverlapping calls validateAndNormaliseDateList() for both args" () {
List list1 = [new Date(1L), new Date(2L)]
List list2 = [new Date(2L), new Date(3L)]
GroovySpy(DateService, global: true) // GroovySpy allows for global replacement. see `org.spockframework.mock.IMockConfiguration#isGlobal()`
when:
DateService.isOverlapping(list1, list2)
then:
1 * DateService.isOverlapping_validateAndNormaliseDateList('first', list1) // groovy 2.x currently allows private method calls
1 * DateService.isOverlapping_validateAndNormaliseDateList('second', list2)
}
I have the following auto-generated code:
EDIT: It's auto-generated so I'm not allowed to modify it. (If only it were that easy...)
abstract class Foo {
}
class Fuwa extends Foo {
String chocolate() {...}
String muffin() {...}
}
class Fuko extends Foo {
String chocolate() {...}
String cookie() {...}
}
The chocolate() method in both the child classes are literally (aside from variable names) line-for-line identical and essentially interchanable.
Based on client input, I want test the specified children of Foo and validate the response. Currently I have:
class FooFactory {
Foo createFoo(name) {
if (name.equals("fuwa")) {
...
// returns a Fuwa object
} else if (name.equals("fuko")) {
...
// returns Fuko object
}
}
}
class MuffinTester extends FooTester {
boolean test(Foo inputFoo) {
Result x = ((Fuwa) inputFoo).muffin();
return validate(x);
}
private validate(x) {...}
}
class CookieTester extends FooTester {
boolean test(Foo inputFoo) {
Result x = ((Fuko) inputFoo).cookie();
return validate(x);
}
private validate(x) {...}
}
class TesterFactory {
FooTester createTest(name) {
if (name.equals("muffin")) {
...
// returns MuffinTester object
} else if (name.equals("cookie")) {
...
// returns CookieTester object
} else if (name.equals("chocolate")) {
...
// returns ChocolateTester object
}
}
}
The client specifies the Foo and method to be tested and the FooFactory and TestFactory (respectively) instantiate the required objects (there is logic to make sure the request is valid and the Foo contains the method, eg. no testing cookie() on Fuwa).
The problem arises when I try to code ChocolateTester:
class ChocolateTester extends FooTester {
boolean test(Foo inputFoo) {
Result x = ((???) inputFoo).chocolate();
return validate(x);
}
private validate(x) {...}
}
I can't leave inputFoo as just Foo since the compiler doesn't like that it doesn't have a chocolate() method. And I can't cast inputFoo to Fuwa or Fuko since whichever one I don't cast it to gets annoyed that they're being confused with their sibling (even though they're identical when exposed to chocolate for all intents and purposes). It would be great if I could modify Foo, but since it's auto-generated I can't touch it.
The best I could come up with is a bunch of if/else statements:
class ChocolateTester extends FooTester {
boolean test(Foo inputFoo) {
Result x;
if (inputFoo instanceof Fuwa) {
x = ((Fuwa) inputFoo).chocolate();
} else if (inputFoo instanceof Fuko) {
x = ((Fuko) inputFoo).chocolate();
}
return validate(x);
}
private validate(x) {...}
}
But feels really hacky when there are some 15 or so Foo and I have to duplicate the giant if/else block in for other methods the children Foo have in common, say a cake() method. Moreover, this sounds like a maintenance nightmare when a new Foo named Futaro joins in and I have to update the if/else blocks in not only FooFactory but also in ChocolateTester and CakeTester and in any other common methods.
So...
I'm sorry for being so long winded, but basically I want to ask is there a better way to do this (that is not too hacky/unmaintainable)? Is there a simple annotation to force method call to a method which doesn't exist, or a way to cast an object to its actual type, or a use of reflection which can solve this?
Update: I ultimately decided to use reflection with method invocation, see below.
Yes there is!
You can create abstract methods inside of Foo like this:
abstract class Foo {
abstract String Chocolate();
}
OR you turn Foo into an Interface, forcing any implementing classes to have a chocolate() method:
interface Foo {
String chocolate();
}
class Fuwa implements Foo {
String chocolate() {...}
String muffin() {...}
}
class Fuko implements Foo {
String chocolate() {...}
String cookie() {...}
}
After automatically generating the code, you could post-process it to add a suitable interface to the child classes. The exact method you'd use to do this would depend on what build automation you're using already. For example, if you're using ant to run the axis2 code generator, then it'd be straightforward to add some additional steps to the code-generation target that changed each of the generated files.
I posed this question to my boss and what he suggested was that I use reflection to invoke the method.
So in this case:
class ChocolateTester extends FooTester {
boolean test(Foo inputFoo) {
Method chocolateMethod = inputFoo.getClass().getMethod("chocolate");
Result x = chocolateMethod.invoke(inputFoo);
return validate(x);
}
private validate(x) {...}
}
I would need to add some code validate that inputFoo indeed had a chocolate() method and to catch all the exceptions, but this seems like the best solution given the constraint that I cannot modify the auto-generated code.
I'm looking for a way to mock or otherwise stub the functionality of a parent class in a unit test for its childs constructor. The Parent class itself is poorly designed, but untouchable due to contractual agreement. We're using PowerMockito already, but PowerMock(EasyMock) is also on the list of approved libraries. Here's the simplified code, along with my best attempt thus far at getting the unit test working:
/**
* The class Parent is locked
*/
public class Parent {
private final Integer x;
private final Integer y;
public Parent(Integer x) {
this.x = x;
this.y = loadY();
}
private int loadY() {
// Actual code loads a bunch of stuff from DB
throw new RuntimeException();
}
protected Integer getSum() {
return x+y;
}
}
/**
* This code is not locked, but Child MUST extend Parent and foo MUST be final.
*/
public class Child extends Parent{
private final Integer foo;
public Child(int x) {
super(x);
foo = getSum();
}
public Integer getFoo() {
return foo;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({Child.class, Parent.class})
public class ChildTest {
#Mock
private Parent par;
#Test
public void testGetFoo() throws Exception {
MemberModifier.suppress(MemberMatcher.constructor(Parent.class, Integer.class));
PowerMockito.whenNew(MemberMatcher.constructor(Parent.class)).withNoArguments().thenReturn(par);
Mockito.when(par.loadY()).thenReturn(new Integer(3));
Mockito.when(par.getSum()).thenReturn(7);
Child child = new Child(4);
Assert.assertEquals(new Integer(7), child.getFoo());
}
}
I am able and willing to edit the class Child so long as it continues to extend Parent and foo is final, but I am unable to edit Parent in any way. It would be more ideal to mock the call to getSum() as that would allow the verification of that call (not relevant here, but it could be in other scenarios). Still, mocking loadY() or setting the state of child.y seems acceptable, but setting child.foo does not seem correct. I've spent a large chunk of the day bouncing back and forth between websites and eclipse trying to figure this out, but so far every run results in the expectable RTE or NPE. Any Ideas?
I have a public class, which needs 7 parameters to be passed down. At the moment, I am able to make 3 of them being passed to constructor and another 4 to a public method in the class . Like this:
Public Class AClass{
private XClass axClass;
private String par4;
private String par5;
private String par6;
private String par7;
public AClass(String par1, String par2, String par3){
aXClass = new XClass(par1,par2,par3);
}
public execute(String par4,String par5, String par6, String par7){
//this is needed because they are used in other private methods in this class
this.par4 = par4;
this.par5 = par5;
this.par6 = par6;
this.par7 = par7;
//call other private methods within this class.
//about 7 lines here
}
}
My question is, is this the right way to ask client of the class to passing in paramters?
There shouldn't be anything stopping you from passing 7 parameters to a constructor, if that's what you want. I don't know if there's a maximum number of parameters that can be passed to a method in Java, but it's certainly higher than 7 if there is a max.
When you create a class and its public methods, you're creating an interface on how to use and access that class. So technically what you've done so far is correct. Is it the "right way" to ask the client of a class to pass in arguments? That's up to you, the designer of the interface.
My first instinct when I saw 7 parameters being passed was to silently ask "Is there some relationship between some or all of these parameters that might mean they'd go together well in a class of their own?" That might be something you address as you look at your code. But that's a question of design, not one of correctness.
I'd go for the Builder Pattern instead of many constructor parameters as suggested by
Effective Java Item 2: Consider a builder when faced with many constructor parameters
Here's a simple class to illustrate:
public class Dummy {
private final String foo;
private final String bar;
private final boolean baz;
private final int phleem;
protected Dummy(final Builder builder) {
this.foo = builder.foo;
this.bar = builder.bar;
this.baz = builder.baz;
this.phleem = builder.phleem;
}
public String getBar() {
return this.bar;
}
public String getFoo() {
return this.foo;
}
public int getPhleem() {
return this.phleem;
}
public boolean isBaz() {
return this.baz;
}
public static class Builder {
private String foo;
private String bar;
private boolean baz;
private int phleem;
public Dummy build() {
return new Dummy(this);
}
public Builder withBar(final String bar) {
this.bar = bar;
return this;
}
public Builder withBaz(final boolean baz) {
this.baz = baz;
return this;
}
public Builder withFoo(final String foo) {
this.foo = foo;
return this;
}
public Builder withPhleem(final int phleem) {
this.phleem = phleem;
return this;
}
}
}
You would instantiate it like this:
Dummy dummy = new Dummy.Builder()
.withFoo("abc")
.withBar("def")
.withBaz(true)
.withPhleem(123)
.build();
The nice part: you get all the benefits of constructor parameters (e.g. immutability if you want it), but you get readable code too.
Can't you just make a class/hashmap that stores these parameters and pass this to the function?
public excute(Storageclass storageClass){
//this is needed because they are used in other private methods in this class
this.par4 = storageClass.getPar4();
this.par5 = storageClass.getPar5();
this.par6 = storageClass.getPar6();
this.par7 = storageClass.getPar7();
//or
this.storageClass = storageClass;
}
I don't really see the problem with that.
In any case you could create a "Request" object or something like this:
class SomeClass {
private String a;
private String b;
....
public SomeClass( Request r ) {
this.a = r.get("a");
this.b = r.get("b");
...
}
public void execute( Request other ) {
this.d = other.get("d");
this.e = other.get("d");
...
}
}
See also: http://c2.com/cgi/wiki?TooManyParameters
Without knowing the use of the child class, I can say that there is nothing inherently wrong with what you have done.
Note though that you have to declare
private XClass axClass;
in the variables of your AClass.
However, you say 'I am able to make....' Does this mean there is some problem with declaring this another way?
I don't care for it much, because an object should be 100% ready to be used after its constructor is called. It's not as written in your example.
If the parameters passed into the execute method can simply be consumed, and that's the method of interest for clients, I see no reason for them to be data members in the class.
Without knowing more about your ultimate aims it's hard to tell. But I would re-think this implementation.
If you're planning on introducing an AClass.someMethod() that needs to know par4-7 without requiring you to have called AClass.excute(), then clearly you should be passing the parameters in the constructor.
On the other hand: if you can construct an instance of this object with only par1-3 and do something meaningful with it besides call excute() then it makes sense to allow the object to be constructed with fewer than the full seven parameters.
Yet my own aesthetic is to try and limit the number of "modes" that an object can be in which make certain methods work and others fail. So ideally, a fully-constructed object is ready to run any method the programmer might call. I'd worry about the design issue more than be too concerned about the sheer number of parameters to the constructor.
But as others have pointed out, sometimes there is a natural grouping of these parameters which can deserve objects of their own. For instance: in many APIs instead of passing (x, y, width, height) all over the place they use rectangle objects.
As others already wrote, it is technically correct to pass 7 parameters, although not very 'user-friendly', if you can say so.
Since you didn't write much about this class, I can suggest one small thing: in constructor you're just creating XClass object, so it would be sane to create this object before and pass it as a single parameter.
Something like this:
...
XClass aXClass = new XClass(par1, par2, par3);
AClass aClass = new AClass(aXClass);
...
And this is the constructor:
public AClass(XClass aXClass) {
this.aXClass = aXClass;
}
I'm working on some classes that get part of their configuration from global variables, e.g.
class MyClass {
public void MyClass(Hashtable<String, String> params) {
this.foo = GlobalClass.GLOBALVAR.get("foo");
this.bar = GlobalClass.GLOBALVAR.get("bar");
this.params = params;
}
}
This is bad for a couple of reasons, GLOBALVAR talks to a database to get some of the variables and this makes it really hard to make unit tests. The other problem is that I have many (dozens) of classes that inherit from MyClass, so I can't easily change the constructor signature.
My current solution is to create an additional default constructor and setter methods for params, foo and bar.
class MyClass {
// Other code still here for backwards compatibility.
public void MyClass() {
// Do nothing much.
}
public void setParams(Hashtable<String, String> params) {
this.params = params;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
Any ideas on a good way to refactor this, besides the way I did it? My other thought would be to use a factory method, but I'm afraid I'll run into polymorphic substitution problems.
I think I would start by doing the following. It let's your existing code work without modification, and allows you to add new constructors to the subclasses as you can. Once all of the subclasses have the new constructor, and all of the calls to the old constructors are gone, you can get rid of the GlobalClass and the constructors that use it. You can also then, hopefully, work on cleaning up the GLOBALVAR (the Car class in my code).
import java.util.Hashtable;
class MyClass
{
private final Foo foo;
private final Bar bar;
private final Hashtable<String, String> params;
public MyClass(final Hashtable<String, String> params)
{
this(params, GlobalClass.GLOBALVAR);
}
// added constructor
public MyClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
this.foo = fooBar.getFoo();
this.bar = fooBar.getBar();
this.params = params;
}
}
class MySubClass
extends MyClass
{
public MySubClass(final Hashtable<String, String> params)
{
super(params);
}
// added constructor
public MySubClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
super(params, fooBar);
}
}
// unchanged
class GlobalClass
{
public static Car GLOBALVAR;
}
// added interface
interface FooBar
{
Foo getFoo();
Bar getBar();
}
class Car
// added implements
implements FooBar
{
private Foo foo = new Foo();
private Bar bar = new Bar();
public Object get(final String name)
{
if(name.equals("foo"))
{
return (foo);
}
if(name.equals("bar"))
{
return (bar);
}
throw new Error();
}
// added method
public Foo getFoo()
{
return ((Foo)get("foo"));
}
// added method
public Bar getBar()
{
return ((Bar)get("bar"));
}
}
// unchanged
class Foo
{
}
// unchanged
class Bar
{
}
I think you should introduce an interface to put a layer of abstraction between the global variable collection and its consumers.
interface GlobalVars {
String get(String key);
}
You should introduce a constructor with limited scope, probably package-private
MyClass(GlobalVars globals, Map<String, String> params) {
// create the object
}
And then provide public static factory methods to use this constructor.
public static MyClass newMyClass(Map<String, String> params) {
return new MyClass(GlobalClass.GLOBAL_VAR, params);
}
With this design you can pass in a mock implementation of GlobalVars in a unit test from within the same package by explicitly invoking the constructor.
Addendum: Since params seems to be a required field, I would definitely make it final and avoid the approach where you add mutators to overwrite them.
private final Map<String, String> params;
Also, make a defensive copy to prevent l33t h4x.
this.params = Collections.unmodifiableMap(params);
Your class should take all of its dependencies in the constructor. It's a good idea to make it impossible to create an invalid or uninitialized instance of classes. Make foo and bar private and final, and set them in the constructor.
A slight variation on your approach would be to have an object of type GLOBALVAR in the class and use that instead of the actual global (that refactoring should be a simple search/replace). You can default the new variable to the actual global variable and provide an override for testing.
This GlobalClass.GLOBALVAR should be chopped up up into logical units. That way it would be easier to make mock objects for the unit tests. For example in my CAD/CAM metal cutting application I have a MaterialList, a SheetSizeList, PartNestingParameters, etc.
I don't have a huge list of variables stuff into one giant AppParameter class. They all hang off a ShopStandards object. For Unit Test involving a specific PartNestingParmeters I will just go ShopStandards.PartNestingParmeters = new MockPartNestingParameterTest114(). The test will run not realizing that the Part Nesting Parameters are a mockup. Plus this save me from having to doing dozens of assignments just to get the ShopStandard setup correctly for the test.
We have even more automated where many of the Mock load from files saved during the test run during initial development.
Since you mention that you have the freedom to modify the class hierarchy.
Change the base MyClass ctor to take in 3 parameters params, foo and bar. Comment out the GlobalVar references and simply cache passed in values
Compile.. this should throw up a bunch of compile errors - no ctor which takes 1 parameter.
Fix each one to pass in GlobalVar.get("foo") and GlobalVar.get("bar"). Get it to build.
Refine: Now minimize hits to the DB by lazy load and caching the foo and bar values. Expose via some property on GlobalVar.