This async unittest never fails when it should

I'm bothered by this test below, where it never fails

var should = require('should');
var helper = require("node-red-node-test-helper");
var targetNode = require("../node.js");

helper.init(require.resolve('node-red'));

describe('Dummy Node', function () {
//  this.timeout(10000);

  beforeEach(function (done) {
      helper.startServer(done);
  });

  afterEach(function (done) {
      helper.unload().then(function() {
        helper.stopServer(done);
    });
  });

  it('should be loaded', async () => {
    var flow = [{ id: "n1", type: "dummy", name: "dummy node" }];
	try {
	    await helper.load(targetNode, flow);
		var n1 = helper.getNode("n1");
		n1.should.have.property('name', 'dummy node');
	} catch (e) {
	}
  });

  it('should make payload lower case', async () => {
    var flow = [
	    { id: "n1", type: "dummy", name: "dummy node", wires:[["n2"]] },
	    { id: "n2", type: "helper" }
	];
    await helper.load(targetNode, flow);
	var n2 = helper.getNode("n2");
	var n1 = helper.getNode("n1");
    n2.on("input", (msg) => {
		try {
	        msg.should.have.property('payload', {'name': 'x'});
		} catch (e) {
		}
    });
	n1.receive({ topic: "", payload: "toupper" });
  });
});

This test is adapted from the node-red-node-test-helper example. The callback version used in the original example works fine.
But after I tried to convert it to the async-await style. It always passes, to my surprise.
For example, in the above code, I made the expected result a wrong value "x", where the correct result should be "TOUPPER". However, the test always passes.

Where am I wrong?

If you make the test an async function, then whether it passes or fails will depend on how the promise it returns is resolved.

Currently, you don't return anything, so the function is resolving cleanly. Where you have the msg.should.have.. statement is inside the input event handler, which is called asynchronously to the call to n1.receive. This means there is no relationship between the async event of the input handler and what the test case is returning. Plus you have the msg.should statement wrapped in a try/catch, so the error doesn't go anywhere useful.

One possible approach would be to wrap the test in a promise:

  it('should make payload lower case', async () => {
    var flow = [
	    { id: "n1", type: "dummy", name: "dummy node", wires:[["n2"]] },
	    { id: "n2", type: "helper" }
	];
    await helper.load(targetNode, flow);
    return new Promise((resolve, reject) => {
        var n2 = helper.getNode("n2");
        var n1 = helper.getNode("n1");
        n2.on("input", (msg) => {
			try {
		        msg.should.have.property('payload', {'name': 'x'});
				resolve()
			} catch (e) {
				reject(e)
			}
	    });
		n1.receive({ topic: "", payload: "toupper" });
	})
  });

But personally, I prefer to use the callback method described in the docs.

Thanks a lot, Nick! I'm still quite a noob at async coding. Your help is much appreciated.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.