Getting Started: JS Testing & Debugging for Apigee with TypeScript & Mocha

I am writing this article in case anyone else needs a quick and easy guide to get up and running with simple unit testing and debugging of their Javascript/TypeScript policy code. With this guide, you can get up and running with TypeScript & Mocha for your Javascript policies in <15 minutes. Promise! (this is a Javascript project after all..)

#Background

Why choose Mocha as Javascript testing framework? Because it just worked with no complexity or difficulty in getting setup and running within a couple of minutes. Plus it seems to be one of the most common and most-used JS testing frameworks out there.

I use TypeScript for similar reasons - it is very well supported, works out-of-the-box in VSCode, and helps me write better and more maintainable Javascript code, and because the tooling is so good, it's really no additional effort.

#MyApproach

I chose a slightly different approach to some of the other Mocha guides here - I do not want to replicate the Apigee Javascript context in my libraries or tests. My approach is to keep the Apigee parts in Apigee, and just have my Javascript code offering clean, generic services to Do Stuff, which then I can call from Apigee Javascript policies with data from the proxy context. That's all. The problem I had though was that the Do Stuff is sometimes a little more complex, and so I need testing and debugging properly supported to develop it effectively.

And yes, normally you would use Java for that (a typed language after all), but thankfully with TypeScript we can now do it with a scripting approach, with is much less effort for me to develop than with Java (haven't used Java in many years now).

#Setup

I'm assuming you already are using VSCode and npm. To install Mocha just run:

npm install -g mocha

That will install Mocha globally on your machine.

Now install TypeScript globally, if not already installed.

npm install -g typescript

Next, create a root directory for your project. Within that directory create 2 subdirectories - src and test.

Your root project directory should look like this:

Project Root
> src - directory for module library code
> test - directory for test code

Now init your TypeScript and node project in the root directory with:

tsc --init
npm init -y

And finally install the Typescript bindings for both Mocha and Node.

npm install @types/node
npm install @types/mocha

#Code

Now create a <name>.ts file in source for your src directory, where <name> is your module name.

Write your logic in this file, just using simple Javascript functions, but with TypeScript typing to make it more type safe, stable and reusable. Using TypeScript interfaces, you can model all of the input and output structures that you expect.

Here is an example pinglib.ts that defines a simple ping method:

// my module function ping that I want to use in my proxy
function ping(ping: string): string {
  return "pong";
}


// this is to only export the function if in node
if (typeof exports !== 'undefined') {
  exports.ping = ping;
}

Now run tsc in your root directory. This is the TypeScript compiler, which will compile all of your *.ts files to *.js files that we can actually run and use.

If all goes well, you should have no errors (no output text). Test changing something in your pinglib.tsc file, you should see an error in VSCode, and also if you run tsc again. That's the cool power of TypeScript! Keeping you safe and typed.

The exports.ping = ping is because we only have an exports module in node, where we want to run mocha tests, but not in Apigee. In Apigee we will just include the file, and call the method directly. Only setting the export when it exists lets us use the same code in both environments.

Now let's write a test to verify (and debug if wanted) our module.

#Test

Create a file test1.ts in your test directory, and add this Mocha test script to your file:

let assert = require('assert');
let pinglib = require('../src/pinglib.js');

describe('Array', function() {
  describe('#ping()', function() {
    it('should return pong', function() {
      assert.strictEqual(pinglib.ping("ping"), "pong");
    });
  });
});

Here we are just testing our ping method, to make sure it returns "pong".

To run the test, first run tsc to compile your ts files into js, and then mocha to run the tests. You should get a green confirmation that the ping test was successful! Woohoo!!

Now you can also add this script tag to your package.json file to run mocha when you run npm test.

"scripts": {
    "test": "mocha"
  }

#Debug

Let's just admit it - sometimes debugging is really, really helpful. We can now debug our module very easily by installing the Mocha Sidebar in VSCode. In the sidebar we can easily run our tests, as well as debug tests by setting breakpoints in our JS code (this is also possible directly in TS code, but I haven't done that yet..).

Open up the pinglib.js file and set a breakpoint in the ping method (on return "pong";)

Now go to the Test sidebar panel, go to the #ping() method, and click the bug symbol to debug. You should land right in your method, and be able to step through your code.

10580-screenshot-2020-11-16-at-212337.png

With this we can develop useful modules in TypeScript, test them with realistic inputs and outputs in Mocha, and also debug them with any input parameters to make sure the module will perform as wanted in our production proxies.

#Add to Apigee

Now you can take your pinglib.js code, add it as a resource in an Apigee proxy, and include it in any Javascript policy configuration, like this:

<IncludeURL>jsc://pinglib.js</IncludeURL>

And with that you can simply call the ping method in your Javascript policy, and it will work within your proxy context. As mentioned at the top of the article, I prefer this to working directly with the Apigee Javascript context object because I can write clean, testable TypeScript modules, and just reuse them in my proxies where needed (and not have the code be dependent on specific context properties, and as a bonus be able to debug the code as well).

Hope this was usable, let me know if you have any questions, or suggestions for improvement.

Version history
Last update:
‎11-16-2020 12:42 PM
Updated by: