Method Chain with Snippet
The problem I'm trying to solve is setting some global state, running a test, and ensuring that the global state is set back to it's original (or correct) value. My usual solution to this problem is to remove global state, but not all global states are created equally. The two global states I've been unsuccessful at removing are the current time and system properties.
In my previous post I described how I freeze time using the Joda library. The example code for freezing time was the first time I used a Method Chain with a Snippet. At the time I thought it was an ugly solution, but the best I could come up with.
A few months later I was testing some code that set and read from the system properties. My first tests set the properties and didn't clean up after themselves. This quickly caused trouble, and I found myself turning to Method Chain with Snippet again.
Here's some example code where I verify that setupDir doesn't overwrite a default property:
@Test
public void shouldNotOverrideDir() {
new Temporarily().setProperty("a.dir", "was.preset").when(new Snippet() {{
new Main().setupDir();
assertEquals("was.preset", System.getProperty("a.dir"));
}});
}
And, here's the code for the Temporarily class
public class Temporarily {
private Map<string, string=""> properties = new HashMap<string, string="">();
public void when(Snippet snippet) {
for (Map.Entry<string, string=""> entry : properties.entrySet()) {
System.setProperty(entry.getKey(), entr</string,></string,></string,><string, string=""><string, string=""><string, string="">y.getValue());
}
}
public Temporarily setProperty(String propertyName, String propertyValue) {
if (System.getProperty(propertyName) != null) {
properties.put(propertyName, System.getProperty(propertyName));
}
System.setProperty(propertyName, propertyValue);
return this;
}
}
The
code works by setting the desired state for the test, chaining the
state cleanup method, and passing the test code as a Snippet to the
state cleanup method. The code exploits the fact that Java will execute
the first method, then the argument to the chained method, then the
chained method.
For the previous example, the 'setProperty'
method is executed, then the Snippet is constructed and the initializer
is immediately executed, then the 'when' method is executed. The
Snippet argument isn't used within the when method; therefore, no state
needs to be captured in the Snippet's initializer.
This pattern
seems to work well whenever you need to set some state before and after
a test runs. However, as I previously mentioned, it's much better if
you can simply remove the state dependency from your test.
From http://blog.jayfields.com/
Jay Fields is a software developer and consultant at DRW Trading. He has a passion for discovering and maturing innovative solutions. His most recent work has been in the Domain Specific Language space where he's delivered applications that empowered subject matter experts to write the business rules of the applications. He is also very interested in maturing software design through software testing. Jay is a DZone MVB and is not an employee of DZone and has posted 13 posts at DZone. You can read more from them at their website.
- Login or register to post comments
- 1613 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)










Comments
Sebastian Mueller replied on Thu, 2009/06/25 - 3:52am
This sure looks like a hammer to me. This code is pretty much over designed to look like a fluent interface but does not do its job very well, IMHO.
If your "Snippet" throws an exception the properties will never be restored. If "Snippet" was a runnable that was only executed at "run()-time" the "when" method could have invoked the runnable and do so within a try finally block, first setting the properites and then restoring them in the finally after the execution of the "snippet". This would have made a little sense at least to me. Because then it would have been possible to actually reuse the "Temporarily" instance and not depend on less obvious-side effects that depend on the execution order.Also the state of the system properties woud have only been modified if the during the execution of "when". Now if you omit the when() the properties will be set some value and will never be reset, either.
Just my 2 cents.
tiffanyjewelry replied on Fri, 2009/06/26 - 1:29am
mgira replied on Fri, 2009/06/26 - 6:05am
andy darlow replied on Sat, 2009/06/27 - 3:14am
i also believe that using Mock objects is the way forward.
The problem that you're experiencing is the age old design problem of singletons. It's made worse when static methods are used to represent singletons.
To solve the problem, I'd recommend creating a class to abstract the functionality of your static methods and then inject an instance of that class into your class (ok, its a siingleton - but at least you can now create an instance of it). .The class is effectively a delegate for the static methods. Once you've done that then you can create mock alternatives to the class and inject them into your class for testing.
Using a class to abstract the behavour normally aids readability as well. In your example, a class called, say, FileSystem (or what ever) whould help the reader understand what the property a,dir is all about. Currently. looking at the code, I don't know what a.dir is.
Hope that this helps
If you need examples then just say amd I'll post.
Cheers
Andy