Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

td.replaced module still returning stub after a td.reset() #373

Closed
3 tasks
TheHandsomeCoder opened this issue May 22, 2018 · 7 comments
Closed
3 tasks

td.replaced module still returning stub after a td.reset() #373

TheHandsomeCoder opened this issue May 22, 2018 · 7 comments

Comments

@TheHandsomeCoder
Copy link

TheHandsomeCoder commented May 22, 2018

Description

calling td.replace a second time on an imported module still resolves the original td.replace Is it possible to td.replace the same module more than once between different describe blocks?

Issue

td.reset() doesn't seem to reset a replaced module.

I have a module that exports a non default function that returns a promise.

import * as AWS from 'aws-sdk';

export const getFileFromS3 = (Bucket: string, Key: string): Promise<any> => {
    const S3 = new AWS.S3();
    return S3.getObject({ Bucket, Key }).promise();
};

The setup/teardown and sample tests are as follows.

describe('test', () => {
    describe(success promise, () => {
        beforeEach(() => {
            td.replace('../../../src/helpers/s3_helper', { getFileFromS3: () => Promise.resolve(new Buffer('test')) });
        });
        afterEach(() => {
            td.reset();
        });
        test('success', () => { // passes as the stubed module resolves the correct data.
                const controller = require('./controller.js');
                 expect.assertions(1);
                return controller.get().then((data) => expect(data).toEqual(new Buffer('test')));
        });
    });
    describe(reject promise, () => {
        beforeEach(() => {
            td.replace('../../../src/helpers/s3_helper', { getFileFromS3: () => Promise.reject('Something went wrong') });
        });
        afterEach(() => {
            td.reset();
        });

        test('failure', () => { //fails as the the promise resolves successfully and catch block isn't triggered
            const controller = require('./controller.js');
            expect.assertions(1);
            return controller.get().catch((error) => expect(error).toEqual('Something went wrong'));
        });
    });
});

My expectation is that after the final td.reset() in the first describe block I should be able to once again replace the s3_helper to this time reject the promise to cover my other test cases. Having debugged my unit tests I have found this not to be then case and whatever I replace the module with originally is returned even after subsiquent replace calls.

When the second test is run in isolation or moved to execute first it works as expected. So more than likely this is to do with me incorrectly setting up my tests.

Environment

  • node -v: 8.9.4
  • npm -v: 5.6.0
  • testdouble@3.8.1:
@searls
Copy link
Member

searls commented May 23, 2018

Thank you for this example. Seems like a bug as far as I can tell by glancing at it. We'll want to start with a reproducing test in the build.

@TheHandsomeCoder
Copy link
Author

If there's anything else I can help with please let me know!

@searls
Copy link
Member

searls commented May 23, 2018

If you'd like to send a PR to add a failing test reproducing this to our test/safe suite, that'd be the next step in solving this.

@TheHandsomeCoder
Copy link
Author

Sure thing, I'll see can I get it in this evening. Is there a prefered suite you'd like this added to?

@searls
Copy link
Member

searls commented May 23, 2018

yes, look under test/safe for other examples of functional tests which call thru to the top-level library and use fixture files to exercise td.replace

@TheHandsomeCoder
Copy link
Author

TheHandsomeCoder commented May 24, 2018

I attempted to replicate the issue in the TestDouble repo yesterday evening and wasn't successful.

I went so far as to replicate nearly exactly the code that I have in my project with the exception of adding Typescript and transpiling. After this failed I went back to my project to see if there is anything I could change in my function that may make it easier to test. So I changed the function from a non-default export to a static function on a default export like so. I did this as I had other dependencies that were resetting correctly and this was the only difference.

import * as AWS from 'aws-sdk';

export default class S3Helper {
    public static getFileFromS3(Bucket: string, Key: string): Promise<any> {
        const S3 = new AWS.S3();
        return S3.getObject({ Bucket, Key }).promise();
    }
}

After doing this all my tests started working as expected... Not sure if this is helpful or not

@searls
Copy link
Member

searls commented Jun 4, 2018

I don't really understand why this worked, but I'm going to close until we can reproduce.

Usually the reason this sort of thing "fixes" the problem is because some module somewhere is doing something to cache itself on first load outside the normal Node.js module cache, which in turn defeats how quibble tries to avoid test pollution

@searls searls closed this as completed Jun 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants