Sinon stub returning the mocked value of previous test case

Viewed 469

I'm having a problem that's really making me crazy.

I'm trying to test a function from a method I've implemented that should have 2 different outcomes based on the return of some intermediate functions. So, I'm using sinon to mock an intermediate function return value (in reality it would call an API) but the problem is that for the first test the mocked result is correct, but in the second the result remains the same I specified in the first one and not the new mock I'm trying to do.

I'm restoring the mock in a afterEach, but it's still not working.

My code as follows:

import * as exportedFuncs from './src/utilFuncs';

import assert from 'assert';
import sinon from 'sinon';

describe('Utils', () => {
  let mock: any;
  beforeEach(function() {
    mock = sinon.stub(exportedFuncs, 'setDefault');
  });

  afterEach(function() {
    mock.restore();
  });

  it('Func should return a default prop', async () => {
    const mockedRequest = {
      hostname: 'www.example.com'
    };
    const ctx = { req: mockedRequest, userName: 'test', password: 'someLongPass12345$$' };

    mock.returns(
      Promise.resolve({
          code: 'test'
        })
    );
    
    const result = await exportedFuncs.buildInfo(ctx);

    let code = result?.defaultValue?.code;

    assert('defaultValue' in result);
    assert.strictEqual(code, 'test');
  });

  it('Func should return a redirectUrl', async () => {
    const mockedRequest = {
      hostname: 'www.example.com'
    };

    const ctx = { req: mockedRequest, userName: 'test', password: 'someLongPass12345$$' };

    mock.returns(Promise.resolve(null));

    sinon.stub(exportedFuncs, 'getRedirect').returns(
      Promise.resolve({
         toUrl: 'www.sample-redirect.com',
         statusCode: 302
       })
    );

    const result = await exportedFuncs.buildInfo(pipelineContext);
    console.log('result',result);

    // the properties have different names because they're parsed by another internal function
    const { redirectStatusCode, redirectUrl } = result.redirect;

    assert.strictEqual(redirectUrl, 'www.sample-redirect.com');
    assert.strictEqual(redirectStatusCode, 302);
  });
});

The result I'm having in these tests is that the first one is passing, as expected, but the second one fails and the console.log shows:

{
  defaultValue: {
    code: 'test'
  },
  redirect: null
}

which is the expected result of the first test case after the mock. What I was expecting it to return was:

{
  defaultValue: null,
  redirect: {
    redirectUrl: 'www.sample-redirect.com',
    redirectStatusCode: 302
  }
}

Also, If I comment the first test case and run the second one only, the test passes.

Can you guys tell me what I'm doing wrong here?

Thank you very much.

1 Answers

You need to declare and refer to that variable using this.mock, instead of declaring it as a closure (let mock: any)

Async tests run in parallel, and both tests are accessing the same variable simultaneously. That is why you see this behavior.

Just make sure to use function() { ... } instead of () => { ... } syntax in your test functions, otherwise it won't work as expected.

Related