Unit tests in Groovy for Java code - how to mock java classes?
I'm introducing Groovy in a large project written in Java, starting (as most of guys do) with writing unit test in Groovy for Java classes.
So the problem I have is:
Imagine I have 2 Java classes, ClassA and Cla开发者_C百科ssB, interacting this way:
public class ClassA {
public void doSomething(...) {
...//something
ClassB.invokeSomeStaticMethod((someParam);
...//something
}
}
ClassB is service looking up some data from database. I'm testing ClassA functionality. So I would like to mock ClassB somehow, so it's invokeSomeStaticMethod() in the context of my unit test would return mocked value for testing. As far as I understand the main problem here is that both classes are Java and hence ClassB.invoke... method is not routed thru Groovy MOP, which the Groovy Mocks are based on. Am I right? And how could I achieve what I need?
Thanks! Mikhail
Static methods, like singletons, are death to testability. While this is a little less so in dynamic languages like Groovy, certinaly here, you've struck a classic testability issue.
The solution is to externalize your dependency, and remove the static method from ClassB
public class ClassA(ClassB classB)
{
ClassB classB
public void doSomething()
{
classB.invokeSomething();
}
}
This approach has two benenfits:
ClassA
is nolonger tightly coupled toClassB
. It can be replaced with a subclass, or a mock.ClassA
now advertises it's dependency onClassB
for the world to know, rather that relying on runtime errors to let developers know that something is missing.
The excellent article Singletons are Liars (from the Google Testing blog) does an excellent job of exploring this concept.
AFAIK, Groovy MOP won't be able to replace the call to ClassB.invokeSomeStaticMethod(someParam)
. You can use a framework like JMockit to help you mock the static method.
Well, I though meta-programming might help, but once ClassB is called from Java code its metaClass won't work.
Mock static method with no parameters in Groovy
精彩评论