Frnak
Frnak

Reputation: 6812

Match a partial object with node:assert / assert arguments of mocked function

I have a mock and want to make sure that it was called with a specific set of arguments. However, I do not want to loop through all calls first.

it("should assert args", (t) => {
  const loggerSpy = t.mock.method(Logger, "info");
  myFunctionUnderTest();
  // this will obivously not work
  assert.deepStrictEqual(loggerInfoSpy.mock.calls, { arguments: [2, "No consumer application for given code", "MODEL_ENERGY_FLOW"] });
}) 

Is there a way to have an assertion like this? Basically I want to have something that would look in jest like this:

expect(
  loggerInfoSpy.mock.calls
).toEqual(
  expect.arrayContaining(
    [{ arguments: [2, "No consumer application for given code", "MODEL_ENERGY_FLOW"] }]
  )
);

Even better ofcourse would be an assertion similar to expect(loggerInfoSpy).toHaveBeenCalledWith(...).

Is there any way to add assertions / extend the node:assert module?

Upvotes: -2

Views: 236

Answers (1)

leitning
leitning

Reputation: 1506

You'll have to create your own helper function to do this, you can attach it to the assert module yourself if you wish. Here's an example:

const { describe, it, before } = require('node:test'),
      { isDeepStrictEqual } = require('node:util'),
      assert = require('node:assert');


assert.calledWith = function(calls, chk) {
  if(calls.mock)
    calls = calls.mock.calls;
  else if(calls.calls)
    calls = calls.calls;
  for(let call of calls) {
    if(isDeepStrictEqual(call.arguments, chk))
      return true;
  }
  assert.fail(`Expected function to be called with ${JSON.stringify(chk)}`);
}

class Foo {
  bar(a,b,c) {
  }
}

describe('foo', function() {
  let foo;
  before(function(t) {
    foo = new Foo();
  });
  it('expect pass', (t) => {
    let spy = t.mock.method(foo,'bar');
    let args = [ 'asdfa', 24342, {x:'y'} ];
    foo.bar(...args);
    assert.calledWith(spy,args);
  });
  it('expect fail', (t) => {
    let spy = t.mock.method(foo,'bar');
    let args = [ 'asdfa', 24342, {x:'y'} ];
    foo.bar(...args);
    assert.calledWith(spy,args.reverse());
  });
});
▶ foo
  ✔ expect pass (0.588027ms)
  ✖ expect fail (0.490436ms)
    AssertionError [ERR_ASSERTION]: Expected function to be called with [{"x":"y"},24342,"asdfa"]
        at assert.calledWith (/tmp/foo/test.js:15:10)
        at TestContext.<anonymous> (/tmp/foo/test.js:38:12)
        at Test.runInAsyncScope (node:async_hooks:206:9)
        at Test.run (node:internal/test_runner/test:631:25)
        at async Suite.processPendingSubtests (node:internal/test_runner/test:374:7) {
      generatedMessage: false,
      code: 'ERR_ASSERTION',
      actual: undefined,
      expected: undefined,
      operator: 'fail'
    }

▶ foo (2.386671ms)

ℹ tests 2
ℹ suites 1
ℹ pass 1
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 8.105062

✖ failing tests:

test at test.js:34:3
✖ expect fail (0.490436ms)
  AssertionError [ERR_ASSERTION]: Expected function to be called with [{"x":"y"},24342,"asdfa"]
      at assert.calledWith (/tmp/foo/test.js:15:10)
      at TestContext.<anonymous> (/tmp/foo/test.js:38:12)
      at Test.runInAsyncScope (node:async_hooks:206:9)
      at Test.run (node:internal/test_runner/test:631:25)
      at async Suite.processPendingSubtests (node:internal/test_runner/test:374:7) {
    generatedMessage: false,
    code: 'ERR_ASSERTION',
    actual: undefined,
    expected: undefined,
    operator: 'fail'
  }

Upvotes: 2

Related Questions