Rusty Shackleford
Rusty Shackleford

Reputation: 155

Angular Unit Test - help spying on angularfire arrayUnion and arrayRemove

I have two similar functions to create/remove items in an array, and the unit tests are blowing up once I hit the arrayUnion and arrayRemove functions from firestore. The error seems to indicate that I'm skipping my mock providers and trying to use the real thing. Unfortunately I can't figure out what I need to mock to intercept the arrayUnion and arrayRemove calls so they don't cause the error below.

I noticed that in my service, when I import the functions they come from 2 different places but I couldn't quite figure it out.

import { arrayRemove, arrayUnion } from '@angular/fire/firestore';
import { AngularFirestore } from '@angular/fire/compat/firestore';

Error

    Error: Either AngularFireModule has not been provided in your AppModule (this can be done manually or implictly using provideFirebaseApp) or you're calling an AngularFire method outside of an NgModule (which is not supported).

service.ts

  createCharacterPartyLink(characters: any[], name: string, partyId: string) {
    const characterPartyCollectionRef = this.afs.collection<character>('users/' + this.uid + '/Characters/')
    characters.forEach((char: any) => {
      characterPartyCollectionRef.doc(char.characterid).update(
        { memberOf: arrayUnion({ partyId: partyId, partyName: name }) }
      )})}

service.spec.ts

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        { provide: AngularFirestore, useValue: AngularFirestoreMock },
        { provide: AngularFireAuth, useValue: AngularFireAuthMock }
      ]
    });
    service = TestBed.inject(PartyService);
  });
      
it('createCharacterPartyLink Work as Expected', () => {
    const updateObj = {
      update: function () {
        return { 
          arrayUnion: ()=> {

        }}
      },
    };

    const updateSpy = spyOn(updateObj, 'update');

    AngularFirestoreMock.collection.and.returnValue({
        doc: () => {
          return updateObj
        }
      }
    )

    service.createCharacterPartyLink(mockPartyMembers, 'Test Party', '1234')

    expect(updateSpy).toHaveBeenCalled()

  });

Upvotes: 1

Views: 30

Answers (1)

Rusty Shackleford
Rusty Shackleford

Reputation: 155

After coming back to this a few days later, I realized that it had to do with how I was calling the jasmine.createSpyObj in OTHER tests in my spec file. After cleaning up the mocks, the following tests work great for my original service implementation.

arrayUnion spec

  it('createCharacterPartyLink Work as Expected', () => {

    const updateObj = {
      update: function () {
        return { 
          arrayUnion: ()=> {

        }}
      },
    };

    const updateSpy = spyOn(updateObj, 'update');

    AngularFirestoreMock.collection.and.returnValue({
        doc: () => {
          return updateObj
        }
      }
    )

    service.createCharacterPartyLink(mockPartyMembers, 'Test Party', '1234')

    expect(updateSpy).toHaveBeenCalled()

  });

arrayRemove spec

  it('removeCharacterPartyLink Work as Expected', () => {

    const updateObj = {
      update: function () {
        return { 
          arrayRemove: ()=> {

        }}
      },
    };

    const updateSpy = spyOn(updateObj, 'update');

    AngularFirestoreMock.collection.and.returnValue({
        doc: () => {
          return updateObj
        }
      }
    )

    service.removeCharacterPartylink(mockPartyMembers, 'Test Party', '1234') 

    expect(updateSpy).toHaveBeenCalled()

  });

Upvotes: 0

Related Questions