Using Ava with Testdouble

08/05/2022, Fri
Categories: #JavaScript #testing
Tags: #NodeJs

Example of a Simple Test Case

Ava is a unique testing framework in that it is one of the few testing frameworks out there that recognizes observable resolution. It also makes asynchronous testing the default option when you write tests ensuring better performance. Another nice feature of Ava is that it has a nicer assertion output display.

Testdouble is an assertion library which specializes in create 'doubles'. Testdouble is different from Sinon because Testdouble will replace the function outright for which it is substituting when mocking out a function or object. It also makes it easier to track using a 'sandbox' API to alleviate the user from having to restore an original replaced function.

To demonstrate the usage of this testing framework and assertion library, the following modified example taken from Testdouble's Readme will be shown.

// Import the libraries Ava and Testdouble
import test from 'ava';
import * as td from 'testdouble';

// Example adapted from https://testdouble.github.io/testdouble.js/3-getting-started.html#getting-started

// Functions that are defined on the top level will be
// mocked by Testdouble. The functions will be used to build
// up the two classes.
let subject, createRandomProblem, savesProblem, submitProblem;

class MathProblem {
  constructor(createRandomProblem, savesProblem, submitProblem) {
    this.createRandomProblem = createRandomProblem;
    this.savesProblem = savesProblem;
    this.submitProblem = submitProblem;
  }

  generate() {
    const problem = this.createRandomProblem(),
      savedProblem = this.savesProblem.save(problem);
    this.submitProblem(savedProblem);
  }
}

class SavesProblem {
  save() {
  }
}

//...

Continuing in the same file, there will be two blocks. One of which will be for defining the variables for comparison, while the second will be used for making assertions.

//...

class SavesProblem {
  save() {
  }
}

// Ava's test blocks which will contain the testdouble assertions.
// Testdouble creates a 'double' for two functions and an object.
// This is the preparatory block for creating the class instances for
// asserting in the block below.
test.before(() => {
  createRandomProblem = td.func('createRandomProblem');
  savesProblem = td.object(new SavesProblem());

  // Use td.func and not td.function
  // Issue - https://github.com/testdouble/testdouble.js/issues/214
  submitProblem = td.func('submitProblem');
  subject = new MathProblem(createRandomProblem, savesProblem, submitProblem);
});

// Testdouble's assertion are primarily used in this block and they
// checked against the output of the 'double' function.
test('test double', t => {
  td.when(createRandomProblem()).thenReturn('some problem');
  td.when(savesProblem.save('some problem')).thenReturn('saved problem');
  subject.generate();

  // Wrap with an Ava assertion to state that there will not be an error when using
  // Testdouble's verify assertion. This prevents the Ava test from failing.
  t.notThrows(() => { td.verify(submitProblem('saved problem')) });
});