Unit test your server-side JavaScript with Spock

Learn how to use Spock, the powerful Groovy-based specification framework, to unit test your server-side JavaScript with style..

David Norton

Java 8 was recently released with Nashorn - a JavaScript runtime for the JVM. There are many reasons you may want to use JavaScript in your JVM application; for example, validation logic or template code that can be used on both the client and the server.

I am going to show you how to unit test your JavaScript code using Spock. This Groovy-powered specification framework is powerful and expressive, and integrates nicely with existing Groovy (and Java) codebases with its JUnit test runner.

So why should you test your JavaScript code with Spock? I can think of a few reasons:

  1. Tests integrate with your existing Spock / JUnit-powered test suite, reporting, and IDE. 2. If your JavaScript uses Java APIs, you have them available for use. 3. You get all of the things you love about Spock: power assertions, data-driven testing, mocks, and most importantly: readable tests.

Red, red, red, red, green, refactor

Let’s write our test first:

class TransformSpec extends Specification {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName('nashorn');

    def setup() {
        def source = this.class.getResource('/js/transforms.js').text
        engine.eval(source);
    }

    def "transform"() {
        when:
        Map result = engine.invokeFunction('transform', [name: [first: 'James', last: 'Bond']])

        then:
        result.firstName == 'James'
        result.lastName == 'Bond'
    }
}

And let’s stub out our function:

function transform(person) {
    return {}
}

As you would expect, we get a failed test. Let’s implement that:

function transform(person) {
    return {first: person.name.first, last: person.name.last}
}

And here you get the power of the Groovy power assertion. Rather than a generic “Expected James, got undefined”, you get this:

result.firstName == 'James'
|      |         |
|      null      false
[first:James, last:Bond]

	at TransformSpec.transform(TransformSpec.groovy:20)

Let’s change “first” to “firstName” and “last” to “lastName”:

function transform(person) {
    return {firstName: person.name.first, lastName: person.name.last}
}

And we have a green, passing test!

Data-driven testing

As with any other Spock test, you can use the data table to easily repeat tests with various values:

...
    @Unroll
    def "Max of #a and #b is #expectedResult"() {
        when:
        def math = engine.eval('Math')
        def result = engine.invokeMethod(math, 'max', a, b)

        then:
        result == expectedResult

        where:
        a    | b | expectedResult
        0    | 1 | 1
        2    | 1 | 2
        -2   | 1 | 1
        null | 1 | 1
    }
...

Interactions

What about interaction? Suppose we have a JS function that needs to call a callback function. We can pass a closure to stub out the behavior:

def "callback called"() {
    setup:
    engine.eval('''function thing(callback) { return callback('some') + 'thing'; }''')

    when:
    def result = engine.invokeFunction('thing', { return 'SOME' } as Function)

    then:
    result == 'SOMEthing'
}

But we’re really not validating the interaction. We trust that it called the stub, but it’s not ideal. Instead, let’s try a Spock Mock:

def "callback called"() {
    setup:
    engine.eval('''function thing(callback) { return callback('some') + 'thing'; }''')
    def callback = Mock(Function)

    when:
    def result = engine.invokeFunction('thing', callback)

    then:
    1 * callback.apply('some') >> 'SOME'
    result == 'SOMEthing'
}

We can also mock out functions that would normally be defined elsewhere, such as alert():

def "alert called"() {
    setup:
    engine.eval('''function doAlert() { alert('hello'); }''')
    def alert = Mock(Function)
    engine.put('alert', alert)

    when:
    engine.invokeFunction('doAlert')

    then:
    1 * alert.apply('hello')
}

You can pass any implementation of an interface that is annotated with @FunctionalInterface: Consumer, Predicate, Supplier, etc. I chose Function here because it is the most flexible.

Resources

There you have it. I love Spock, and I’m learning to appreciate JavaScript (it’s what you might call an “arranged marriage”). I put the source from this blog post on Github so you can play around with it yourself. Please comment here if you have any questions!

• Nashorn blog • Nashorn - The Combined Power of Java and JavaScript in JDK 8 • How Java 8 handles JavaScript

Share this Post

Related Blog Posts

JavaScript

Extending Angulars $resource Service for a Consistent API

June 3rd, 2014

Extending Angulars $resource service to make it easy to declare resources and REST APIs. Wrapping the $resource service to normalize the REST calls to make it easier to work with promises and the $q service.

Object Partners
JavaScript

Enterprise Mobile – More Than iOS vs Android

April 1st, 2014

Android vs iOS is the wrong question. Our job as mobile consultants is to solve a business problem and use that solution to bring value to the client.

Charlie Horning
JavaScript

Running a Lightweight Static Server with Grunt

February 26th, 2014

Running a Lightweight Static Server with Grunt

Object Partners

About the author

David Norton

Principal Consultant

Software engineer with 9 years of professional application development experience. Passionate about continuous delivery, incremental improvement, and test-driven development.

Background heavy in enterprise Java technologies such as Groovy, Spring, Spock, Gradle, Hibernate, Tomcat, Jenkins. Focus on high-scale web architecture, platform transformation, and team development.