Let us look at the following fictive example. You want to test a static method of a java class “BlogAction”. This method should tell you whether a user can trigger a delete action depending on a configuration property.
The classes under test:
public class BlogAction { public static boolean isDeletePossible() { return ConfigurationOption.allowsDeletion(); } }
class ConfigurationOption { static boolean allowsDeletion() { // code of the Option class omitted, here it always returns false return Option.isEnabled('userCanDelete'); } }
In our test we mock the method of ConfigurationOption to return some special value and test for it:
@TestMixin([GrailsUnitTestMixin]) class BlogActionTest { @Test void postCanBeDeletedWhenOptionIsSet() { def option = mockFor(ConfigurationOption) option.demand.static.allowsDeletion(0..(Integer.MAX_VALUE-1)) { -> true } assertTrue(BlogAction.isDeletePossible()) } }
As result, the test runner greets us with a nice message:
junit.framework.AssertionFailedError at junit.framework.Assert.fail(Assert.java:48) at junit.framework.Assert.assertTrue(Assert.java:20) at junit.framework.Assert.assertTrue(Assert.java:27) at junit.framework.Assert$assertTrue.callStatic(Unknown Source) ... at BlogActionTest.postCanBeDeletedWhenOptionIsSet(BlogActionTest.groovy:21) ...
Why? There is not much code to mock, what is missing? An additional assert statement adds clarity:
assertTrue(ConfigurationOption.allowsDeletion())
The static method still returns false! The metaclass “magic” provided by mockFor() is not used by my java class. BlogAction simply ignores it and calls the allowsDeletion method directly. But there is a solution: we can mock the call to the “Option” class.
@Test void postCanBeDeletedWhenOptionIsSet() { def option = mockFor(Option) option.demand.static.isEnabled(0..(Integer.MAX_VALUE-1)) { String propertyName -> true } assertTrue(BlogAction.isDeletePossible()) }
Lessons learned: The more happens behind the scenes, the more important becomes the context of execution.