Skip to: Site menu | Main content

Groovy 

      Download | Documentation | Developers | Community

An agile dynamic language for the Java Platform

Mocking Static Methods using Groovy Add comment to Wiki View in Wiki Edit Wiki page Printable Version

Suppose you wish to test a class which is dependent on a static call. Is there a way to mock out that call?

Yes, there are two suggested approaches:

  • Using EMC
  • Using JMockit (requires Java 6)

Using EMC

Here we are calling Arrays.sort() directly - normally that would be the problematic code within your class under test.

// non-mocked first to prove it works normally
String[] things = ['dog', 'ant', 'bee', 'cat']
Arrays.sort(things)
println things // => {"ant", "bee", "cat", "dog"}

Arrays.metaClass.'static'.sort = { a ->
    a[0] = 'ewe'
    a[1] = 'fox'
}

things = ['dog', 'ant', 'bee', 'cat']
Arrays.sort(things)
println things // => {"ewe", "fox", "bee", "cat"}

More details about this approach: ExpandoMetaClass - Adding static methods

Using JMockit

If you are in a position to use Java 6, you should also consider using JMockit.

// require(url:'https://jmockit.dev.java.net', jar='jmockit.jar')
// require(url:'https://jmockit.dev.java.net', jar='jmockit-asm2.jar')
// needs to be run with "-javaagent:jmockit.jar"
// and "-Xbootclasspath/a:jmockit.jar;.;jmockit-asm2.jar"
// The bootclasspath option is only required because we are mocking
// a class from the java.* package (part of the bootclasspath for Java)

import mockit.Mockit

// non-mocked first to show normal case
String[] things = ['dog', 'ant', 'bee', 'cat']
Arrays.sort(things)
println things // => {"ant", "bee", "cat", "dog"}

Mockit.redefineMethods(Arrays, MockArrays)

things = ['dog', 'ant', 'bee', 'cat']
Arrays.sort(things)
println things // => {"dog", "elk", "ape", "cat"}

Where MockArrays is the following Java class:

// Java
public class MockArrays {
  public static void sort(Object[] a) {
    a[1] = "elk";
    a[2] = "ape";
  }
}

We use a Java class here because otherwise JMockit tries to replace other GroovyObject methods (e.g. getMetaClass, invokeMethod, ...) and won't find them inside the java.util.Arrays class. Obviously, if your redefining a Groovy class, you can use another Groovy class.

More details: Using JMockit with Groovy.