Mocking a Hessian Web Service Using Groovy
Join the DZone community and get the full member experience.
Join For FreeDuring last month there were a lot of moments when I thought: ‘How cool it is that I can use Groovy to write it’. For instance, I was working on mocking a hessian web service a few days ago. Hessian is binary web service protocol and writing a mock web service might have been a tricky task. At least I though so in the beginning. But it turned out that everything can be done in a clear and neat way if you have right tools. To show how I used Groovy to do it let’s take a very simple interface that has a hessian based implementation:
interface SampleHessianService { String sayHi(String m) }
Our goal is to write an utility class mocking this service so we can write integration tests for our client (for example, a web app). The client of the service uses such a chunk of code to access the service:
def factory = new HessianProxyFactory() def client = factory.create(SampleHessianService, "http://localhost:8080/sample") String response = client.sayHi('John')
To write my mock service in old Java world I would write something like this:
public class MyServlet extends HessianServlet implements SampleHessianService { Object mockObject public String sayHi(String m){ .... //somehow delegate this call to mockObject .... } } MyServlet servlet = new MyServlet(); //creating a jetty server, creating a jetty context context.addServlet(new ServletHolder(servlet), "/sample"); //starting the jetty server
There are a few things that bother me in this approach. If the interface had like 20 methods I would have to implement all of them to delegate all the work to my mockObject. But I don’t work to write this kind of stuff every time I need a Hessian service. Ideally, I would like to pass a Spock mock object (or any other mock object) to generate a Hessian servlet.
The first feature of Groovy I tried to use to improve my old java style version is @Delegate. @Delegate annotation implements all the methods of SampleHessianService for me and delegates all the calls to a specified object:
class SampleHessianService_HessianImpl extends HessianServlet { @Delegate SampleHessianService delegate } def hessian = new SampleHessianService_HessianImpl() hessian.delegate = Mock(SampleHessianService)
It looks much better, doesn’t it? But I still need to write this dummy class. Writing boilerplate code is OK in Java but not in Groovy. So the next step I took was generating SampleHessianService_HessianImpl in runtime:
def type = SampleHessianService def fullName = type.name def className = type.simpleName def classText = """ import com.caucho.hessian.server.HessianServlet class ${className}_HessianImpl extends HessianServlet { @Delegate ${fullName} delegate } """ def gcl = new GroovyClassLoader() def clazz = gcl.parseClass(classText) def res = clazz.newInstance()
There is one thing I don’t like in generators: I have to add an additional step to my build process to do it. But not in Groovy. Using GroovyClassLoader you can parse new classes easily in runtime without any additional steps. Cool.
The result of my work is this very small but useful class:
class HessianServletFactory { HessianServlet createHessianServlet(Map args) { assert args.type instanceof Class, 'type parameter is not passed or is not a class' assert args.delegate, 'delegate parameter is not passed' def classText = genClassText(args.type) def gcl = new GroovyClassLoader() def clazz = gcl.parseClass(classText) def res = clazz.newInstance() res.delegate = args.delegate return res } private genClassText(type){ def fullName = type.name def className = type.simpleName """ import com.caucho.hessian.server.HessianServlet class ${className}_HessianImpl extends HessianServlet { @Delegate ${fullName} delegate } """ } }
The way you can use it in your test:
@Mixin(HessianServletFactory) class HessianServletSpec extends Specification { def 'should create a hessian servlet using a type and a spock mock object'() { setup: 'setting up server part' def service = createHessianServlet(type: SampleHessianService, delegate: Mock(SampleHessianService)) //adding it to jetty, starting jetty and: 'setting up client part' def factory = new HessianProxyFactory() def client = factory.create(SampleHessianService, "http://localhost:8080/sample") when: def response = client.sayHi(NAME) then: service.delegate.sayHi(NAME) >> RESPONSE response == RESPONSE where: NAME = 'John' RESPONSE = 'Hi John' } }
As you can see mocking a hessian servlet using HessianServletFactory is easy. You don’t have to create new classes each time you want to do it, you don’t have to add an additional step to your build process. The only thing you have to do is to specify a type and a delegate. It can be a Spock mock object or just a fake implementation. Also, I’ve used Mixin in my test because the factory doesn’t have any state and I have not wanted to create a dummy receiver: new HessianServletFactory().createHessianServlet(...) I could use a static method here too. But I prefer never use static methods unless it is a one line method that just creates an object.
From http://victorsavkin.com/post/3473984162/mocking-a-hessian-web-service-using-groovy
Opinions expressed by DZone contributors are their own.
Comments