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

MockProvider does not reset the token value of MockInstance #1256

Closed
AE1NS opened this issue Oct 19, 2021 · 10 comments · Fixed by #1993
Closed

MockProvider does not reset the token value of MockInstance #1256

AE1NS opened this issue Oct 19, 2021 · 10 comments · Fixed by #1993

Comments

@AE1NS
Copy link
Contributor

AE1NS commented Oct 19, 2021

First of all, thank you for this awesome plugin. We integrated it in our solutions and its working really great! Unfortunately one thing is not working as I expect it, but maybe its not a bug, but i missunderstood it.

I created an angular injection token and mock it with MockProvider, i.e.

beforeEach(() => {
    TestBed.configureTestingModule({
        providers: [
            MockProvider(myToken, { test: 1 })
        ],
    });
});

Inside an 'it' I override it with another value:
MockInstance(myToken, () => ({ test: 2 }));

When the next 'it' runs, I expect the value to be resettet to '{ test: 1 }' again by the MockProvider call in beforeEach, but I still get the value '{ test: 2 }' here.

Am I using this the wrong way or is this a bug of the framework?

@satanTime
Copy link
Member

Hi @AE1NS,

if you don't install scopes for MockInstance, then this is the cause of the issue.

If you use jasmine, then everything is every easy, you need to add a global reportor: https://ng-mocks.sudo.eu/extra/install#default-customizations

// auto restore for jasmine and jest <27
// declare const jasmine: any;
jasmine.getEnv().addReporter({
  specDone: MockInstance.restore,
  specStarted: MockInstance.remember,
  suiteDone: MockInstance.restore,
  suiteStarted: MockInstance.remember,
});

The same solution works for jest < 27, if you are using jest 27+, then please support this issue: jestjs/jest#11483.
Until the issue has been merged and released, you could use scopes: https://ng-mocks.sudo.eu/api/MockInstance#customization-scopes

describe('suite', () => {
  beforeAll(MockInstance.remember);
  afterAll(MockInstance.restore);
  // ...
});

Please let me know if it helps, or you need further assistance.

@AE1NS
Copy link
Contributor Author

AE1NS commented Oct 21, 2021

Thank you for your response.
We are using jasmine and I forgot to mention that we are using version 12.3.1 right now, because there seems to be some work to update to 12.5+.
I will try to update to the new version and use the scopes.

@AE1NS
Copy link
Contributor Author

AE1NS commented Oct 21, 2021

I updated to latest now and tested it with both approaches, but still have the same issue. When I use MockPovider/MockInstance with a DI service, everything works fine, but when I use it with an injection token, it seems not to get resettet. I can only reset it, when I do another MockInstance with the default value in the beforeEach right now.

@satanTime
Copy link
Member

satanTime commented Oct 21, 2021

Hi @AE1NS,

I see, might you provide a test with the issue?

Also, could you try to use MockReset in afterEach? It should remove any customizations registered via MockInstance.

describe('suite', () => {
  afterEach(MockInstance);
  // ...
});

@AE1NS
Copy link
Contributor Author

AE1NS commented Oct 21, 2021

My test does not finish when I add this. I get this output in karma:
Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)
When I remove it, its working fine again. Does this only run a MockReset()? I also tried it without success.

I think the problem can be reproduced with something like the following suite:
Spec file:

describe('suite', () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                MockProvider(MyToken, { test: 1 })
            ]
        });
    });

    it('runs with a mocked value for the injection token', () => {
        MockInstance(MyToken, () => ({ test: 2 }));
        const service = TestBed.inject(TestService);
         /// ...
    });

    it('runs with the resettet value of the injection token', () => {
        const service = TestBed.inject(TestService);
        // ...
    });
});

Component:

export const MyToken = new InjectionToken('Capacitor', {
    providedIn: 'root',
    factory: () => Capacitor
});

@Injectable({
    providedIn: 'root',
})
export class LogService {
    constructor(
        @Inject(MyToken) private _tokenData: any,
    ) {}

    async test() {
        if (this._tokenData.test === 1) {
            // ...
        }
    }
}

When running the tests synchronously, I expect the 'test' property in the token to be 1, but its in both cases 2 because its not resettet, so the if statement in the implementation is never entered.

@satanTime
Copy link
Member

Ah sorry. My mistake. It should be

afterEach(MockReset);

@AE1NS
Copy link
Contributor Author

AE1NS commented Oct 21, 2021

Well, with the MockReset it works now. But does it mean that there is an issue with MockInstance, because it must be reset automatically?

@satanTime
Copy link
Member

Hi there, a happy new year! :)

I'm back to business and was able to reproduce your issue. It should be fixed soon.

@satanTime
Copy link
Member

the issue here is that MockInstance with callbacks doesn't follow scopes, it will be fixed.

for now, you could use MockInstance(MyToken, 'test', 2);, it works with classes, but not sure yet about tokens :)

satanTime added a commit that referenced this issue Mar 6, 2022
feat(MockInstance): resets root overrides likewise properties #1256
@satanTime
Copy link
Member

v13.1.0 has been released and contains a fix for the issue. Feel free to reopen the issue or to submit a new one if you meet any problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants