Testing Applications and Libraries

Contents

Testing Applications and Libraries

This guide describes how to test libraries and applications using the Enonic XP test framework. It is based on JUnit and uses a mix of Java and JavaScript. Tests must be bootstrapped with Java and then you can write all your tests using pure JavaScript.

The test framework requires Enonic XP 6.12 or newer

All code samples for this Guide is available on Github: https://github.com/enonic/guide-testing-apps.

Add Dependency

First you will need to add the Enonic XP testing dependency to your project.

dependencies {
  testCompile 'com.enonic.xp:testing:6.12.0' (1)
}
1 The testing framework ships with the XP core, replace version number with the version of XP you are compiling for.

Testing a Library

Let’s start with a simple library which is just a plain JavaScript file with some exports. This library here has a function returning a Fibonacci-sequence.

src/main/resources/lib/fibonacci.js
function fibonacci(n) {
    var fib = [0, 1];
    for (var i = fib.length; i < n; i++) {
        fib[i] = fib[i - 2] + fib[i - 1];
    }

    return fib;
}

// Export the function.
exports.fibonacci = fibonacci;

We can write a couple of tests for this. Let’s test the function for a couple of inputs.

src/test/resources/lib/fibonacci-test.js
var lib = require('./fibonacci');
var t = require('/lib/xp/testing');

exports.testSequence4 = function () {
    var result = lib.fibonacci(4);
    t.assertJson([0, 1, 1, 2], result);
};

exports.testSequence6 = function () {
    var result = lib.fibonacci(6);
    t.assertJson([0, 1, 1, 2, 3, 5], result);
};

Every exported function that is prefixed with test is executed as a separate test. You can also export before and after if you need to execute some logic before or after each test.

But, to be able to execute this test you will also need to write a little "bootstrap" code in Java. Here’s how this will look for this particular test:

src/test/java/com/enonic/guide/FibonacciTest.java
package com.enonic.guide;

import com.enonic.xp.testing.ScriptRunnerSupport;

public class FibonacciTest
    extends ScriptRunnerSupport
{
    @Override
    public String getScriptTestFile()
    {
        return "/lib/fibonacci-test.js";
    }
}

Testing a Controller

Testing controllers is identical to what is described in the previous section. For this example we have a simple service that serves a GET request.

src/main/resources/services/hello/hello.js
exports.get = function (req) {
    return {
        body: 'Hello ' + (req.params.name || 'World'),
        contentType: 'text/plain'
    };
};

Let’s write a test that tests two conditions: one where the parameter is not set and another one where the parameter is set.

src/test/resources/services/hello/hello-test.js
var service = require('./hello');
var t = require('/lib/xp/testing');

exports.testParam = function () {
    var result = service.get({
        params: {
            name: 'Donald'
        }
    });

    t.assertEquals('Hello Donald', result.body);
    t.assertEquals('text/plain', result.contentType);
};

exports.testNoParam = function () {
    var result = service.get({
        params: {}
    });

    t.assertEquals('Hello World', result.body);
    t.assertEquals('text/plain', result.contentType);
};

Again, to execute the test we need a little bit of Java.

src/test/java/com/enonic/guide/HelloServiceTest.java
package com.enonic.guide;

import com.enonic.xp.testing.ScriptRunnerSupport;

public class HelloServiceTest
    extends ScriptRunnerSupport
{
    @Override
    public String getScriptTestFile()
    {
        return "/services/hello/hello-test.js";
    }
}

Mocking Services

Sometimes it can be useful to mock certain libraries so it’s easier to test. Let’s say we depend on a library that gives us the time of day. To fix the return value in our tests we need to mock this library.

src/main/resources/lib/time.js
exports.now = function () {
    return new Date().toISOString();
};

Our service that uses the time is like this:

src/main/resources/services/clock/clock.js
var time = require('/lib/time');

exports.get = function () {
    return {
        body: 'Time is ' + time.now()
    };
};

To be able to test this we need to mock our time library in our test so we can return a fixed result.

src/test/resources/services/clock/clock-test.js
var t = require('/lib/xp/testing');

t.mock('/lib/time.js', { (1)
    now: function () {
        return '2017-08-01T12:13:24.000Z';
    }
});

exports.testClock = function () {
    var service = require('./clock'); (2)

    var result = service.get();
    t.assertEquals('Time is 2017-08-01T12:13:24.000Z', result.body);
};
1 Mock the time library so we can control the output.
2 Clock service uses the time library in code. It will get the mocked version.

Contents