auto-spies icon indicating copy to clipboard operation
auto-spies copied to clipboard

accessorSpies in jest-auto-spies + nx workspace not mocking return value

Open GuilleEneas opened this issue 4 years ago • 17 comments

Describe the bug When creating a service with a getter and trying to mock it in a test the returned value is undefined.

To Reproduce Steps to reproduce the behavior:

  1. npx create-nx-workspace
  2. cd to your project
  3. nx g s --name=one --project=app --skipTests
  4. then check the changes in this commit
  5. ng test --watch

and boom

 FAIL  apps/app/src/app/app.component.spec.ts
  ● AppComponent › whatever

    expect(received).toStrictEqual(expected) // deep equality

    Expected: {"fake": "value"}
    Received: undefined

      32 |     const value = componentUnderTest.getGetter();
      33 |
    > 34 |     expect(value).toStrictEqual({
         |                   ^
      35 |       fake: 'value'
      36 |     });
      37 |   });

      at src/app/app.component.spec.ts:34:19
      at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (../../node_modules/zone.js/dist/zone.js:386:30)
      at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (../../node_modules/zone.js/dist/proxy.js:117:43)
      at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (../../node_modules/zone.js/dist/zone.js:385:36)
      at Zone.Object.<anonymous>.Zone.run (../../node_modules/zone.js/dist/zone.js:143:47)

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        3.522s

Expected behavior the test should pass

Desktop (please complete the following information):

  • OS: Mac OSX
  • Browser chrome
  • Version 88.0.4324.146

You can also clone this repo where the issue occurs https://github.com/GuilleEneas/jest-auto-spies-issue

GuilleEneas avatar Feb 10 '21 14:02 GuilleEneas

I checked a bit and the returned object from provideAutoSpy method contains the getter, while after calling TestBed.inject the returned object has the getters striped out.

GuilleEneas avatar Feb 10 '21 15:02 GuilleEneas

Thanks @GuilleEneas !

Sometimes Jest has weird issues with it's caching, did you try cleaning it's cache and run it again?

shairez avatar Feb 11 '21 23:02 shairez

Hi @shairez !

Yes, I did. As I mention before, the method provideAutoSpy seems to work as expected, is the interaction with the test bed injector the one that seems to remove the getters and setters, but keeps the accessorSpies.

GuilleEneas avatar Feb 12 '21 09:02 GuilleEneas

Really weird issue, without debugging I was able to simulate the issue

But when debugging it step by step... I was able to pass the test and see the getters on OneService

WTF 😀

image

shairez avatar Feb 16 '21 10:02 shairez

It might have something to do with the fact that I made a small change to AppComponent (added a method and then removed it).

So I suspect it's an issue with the nx cache or something alike...

shairez avatar Feb 16 '21 11:02 shairez

this is weird, as when I was debugging step by step the injector returned an object without getters. do you suggest it is a nx bug instead?

GuilleEneas avatar Feb 18 '21 14:02 GuilleEneas

Yeah, the first time I debugged it I saw the issue... but then I changed the file a bit... reverted it (but because it was "changed" the timestamp was different I guess) and then I couldn't reproduce anymore.

Try that and let me know if that's the case for you as well

if so, it might be the nx cache

shairez avatar Feb 18 '21 21:02 shairez

I can't make the test pass, even following your steps. I'll try to create this issue with the nx workspace alone to see if this can be an nx issue... do you know if they fix this issues when people submit them. I'll keep you posted 🤓

GuilleEneas avatar Feb 23 '21 15:02 GuilleEneas

Hmm... this is a tricky one.. I guess you'll need to simulate the caching issue in a reproducible way in order for them to fix it

shairez avatar Feb 23 '21 23:02 shairez

I made some more research, the problem is the Object.defineProperty method, somehow that property got stripped out after being inserted and retrieved from the testbed. I created this repos which reproduces the error https://github.com/GuilleEneas/nx-angular-testing-issue . Could you check it (when having time)?... and please let me know if you think is worth reporting (and if they would be interested in fixing it, in your opinion, ofc)

GuilleEneas avatar Feb 24 '21 09:02 GuilleEneas

Wow... good job finding it!

I'll take a look at it next week and report back

Thanks!

shairez avatar Feb 24 '21 10:02 shairez

I've also faced with this issue, but in a non-nx project, so I think this issue is not related to nx.

peterreisz avatar Aug 11 '21 13:08 peterreisz

I having this issue in an Nx project. I've tried nx test --clearCache in case that helps, but when I spy on a simple service like:

@Injectable({
  providedIn: 'root',
})
export class PartyService {
  private _partyId!: number;

  public set partyId(partyId: number) {
      this._partyId = partyId;
  }

  public get partyId(): number {
    return this._partyId;
  }
}

The value is always undefined:

describe('CollegeLicenceInformationPage', () => {
  let component: CollegeLicenceInformationPage;
  let partyServiceSpy: Spy<PartyService>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule,
        ReactiveFormsModule,
        RouterTestingModule,
      ],
      providers: [
        CollegeLicenceInformationPage,
        {
          provide: PartyService,
          useValue: createSpyFromClass(PartyService, {
            gettersToSpyOn: ['partyId'],
            settersToSpyOn: ['partyId'],
          }),
        },
      ],
    });

    component = TestBed.inject(CollegeLicenceInformationPage);
    partyServiceSpy = TestBed.inject<any>(PartyService);
  });

  describe('INIT', () => {
    given('partyId exists', () => {
      const partyId = randNumber({ min: 1 });
      partyServiceSpy.accessorSpies.setters.partyId.mockReturnValue(partyId);

      when('initializing the page', () => {
        component.ngOnInit();

        then(
          'resource should get the college licence information of the party',
          () => {
            expect(partyServiceSpy.partyId).toBe(partyId); // <--- Always undefined
          }
        );
      });
    });
  });
});

mtpultz avatar Mar 01 '22 21:03 mtpultz

@GuilleEneas I cannot reproduce the problem from the second run of the tests (only on the first one it fails) Tried to clear both jest and nx cache but no luck

@peterreisz did it continue to happen?

@mtpultz can you reproduce it consistently and can upload a mini-repo that can show that?

Thanks!

shairez avatar Mar 03 '22 22:03 shairez

@shairez I need to check, this was long ago, I might remember that this wasn't happening when updating nx. I'll check in the following days. just to be clear did you check this repo https://github.com/GuilleEneas/nx-angular-testing-issue?

GuilleEneas avatar Mar 03 '22 22:03 GuilleEneas

@GuilleEneas yep

Btw with a brand new nx I couldn't reproduce

shairez avatar Mar 03 '22 22:03 shairez

@shairez I created a new install of Nx, and was able to quickly reproduce it using a barebones Angular application- https://github.com/mtpultz/jest-auto-spies-error. When you run nx test you see a similar error to the one posted above.

UPDATE: Sorry @shairez looks like I had a typo and was using setters in my statement bonnieServiceSpy.accessorSpies.setters.bonnieId.mockReturnValue(bonnieId); instead of getters bonnieServiceSpy.accessorSpies.getters.bonnieId.mockReturnValue(bonnieId); when using mockReturnValue(...) :(

mtpultz avatar Mar 10 '22 02:03 mtpultz