How to mock AngularFire 2 service in unit test?

前端 未结 3 1831
情话喂你
情话喂你 2021-02-05 12:14

I\'m trying to set up unit tests for a sample Angular 2 app using AngularFire 2 auth, the component is fairly simple:

import { Component } from \'@angular/core\'         


        
相关标签:
3条回答
  • 2021-02-05 12:39

    Similar to @jan, I made a mock using some utility functions:

    import {AngularFireAuth} from '@angular/fire/auth';
    import {AngularFireDatabase} from '@angular/fire/database';
    import {auth} from 'firebase/app';
    
    import { Observable, of, Subscription } from 'rxjs';
    
    /**
     * Mocks the Firebase auth by automatically logging in.
     */
    export const AngularFireAuthMock = jasmine.createSpy('signInWithEmailAndPassword')
          .and.returnValue(Promise.resolve({uid: 'fakeuser'}));
    
    /**
     * Mocks an AngularFireDatabase that always returns the given data for any path.
     */
    export function mockAngularFireDatabase(data): AngularFireDatabase {
      return {
        object: (path: string): any => {
          return {
            valueChanges() {
              return of(data);
            }
          }
        }
      } as AngularFireDatabase;
    }
    

    and then you can use them in your spec like this:

     beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [ TweakComponent ],
          imports: [ MatDialogModule, RouterTestingModule ],
          providers: [
           { provide: MAT_DIALOG_DATA, useValue: {} },
           { provide: AngularFireDatabase, useValue: mockAngularFireDatabase({testdata:'hi'})},
           { provide: AngularFireAuth, useValue: AngularFireAuthMock}
         ],
        })
        .compileComponents();
      });
    
    0 讨论(0)
  • 2021-02-05 12:41

    In this snippet:

    beforeEach(() => addProviders([
      AppComponent,
      AngularFire
    ]);
    

    You set (or override) the providers that will be used in your test.

    That being said, you can create a different class, a mock if you will, and, using the { provide: originalClass, useClass: fakeClass } notation, provide it instead of the AngularFire actual class.

    Something like this:

    class AngularFireAuthMock extends AngularFireAuth {           // added this class
      public login() { ... }
      public logout() { ... }
    }
    
    class AngularFireMock extends AngularFire {                   // added this class
      public auth: AngularFireAuthMock;
    }
    
    beforeEach(() => addProviders([
      AppComponent,
      { provide: AngularFire, useClass: AngularFireMock }         // changed this line
    ]);
    

    And the AngularFires in your tests will be AngularFireMocks.

    0 讨论(0)
  • 2021-02-05 12:48

    hope it is not off the topic, but the easiest solution I have found how to mock the FirebaseDatabase.

    var object = function() {
          var obj = { valueChanges() {
                return of({data:'data'});     
            }
          }
          return obj;
        }
    
    providers: [..., { provide : AngularFireDatabase,
            useValue: {object : object }} ]
    

    instead of data:'data' you can mock whatever data you need. The functions can be modified as you wish.

    0 讨论(0)
提交回复
热议问题