Search code examples
angularunit-testingtypescriptkarma-jasminetestbed

Async test does go trough all functions


When i try to run a test in karma jasmine it should go trough 2 services. However it does all the way to the last function but it does not come back with its return values. Does anyone has a idea how it does not return something?

My beforeEach

 function checklistDbFactory(): PouchDB {
    // ... is just for sharing
    let db = new PouchDB("...");
    PouchDB.plugin(PouchFind);
    return db;
  }


  beforeEach(async(() => {

    TestBed.configureTestingModule({
      imports: [HttpModule],
      providers: [
        {provide: CHECKLIST_DB, useFactory: checklistDbFactory, deps: []},
        DatabaseService,
        IndexService,
        MockBackend,
        BaseRequestOptions,
        {
          provide: Http,
          useFactory: (backend, options) => new Http(backend, options),
          deps: [MockBackend, BaseRequestOptions]
        }
      ]
    });
    backend = TestBed.get(MockBackend);

    service = TestBed.get(IndexService);
  }));

My test itself

it('function should return expectd json', async(() => {
    backend.connections.subscribe(connection => {
      connection.mockRespond(new Response(<ResponseOptions>{
        body: JSON.stringify(expectJson)
      }));
    }); 
    console.log("getting into main thread");
    // ... is just for sharing
    service.filldatabase(inputJson, "...").then((data) => {
      console.log('getting into filldatabase');
      console.log(data);
    });
  }));

filldatabase function

filldatabase(jsonfile, key) {
    console.log('Getting into filldatabase of 1service');
      return this.databaseService.fillPouch(JSON.parse(jsonfile['_body']), key).then( (data) => {
        console.log(data);
        console.log("Getting into then of fillPouch in 1st service");
        return true;
      }).catch( () => {
        console.log("getting into catch of fillpouch in 1service");
        return false;
      });
  }

fillPouch function

fillPouch(json, key) {
    json._id = key;
    let push = this.db.put(
      json
    );
    console.log("push");
    console.log(push);

    return push;
  }

Output of the test on IntlliJ

'getting into main thread'
'Getting into filldatabase of 1service'
'push'
ZoneAwarePromise{__zone_symbol__state: null, __zone_symbol__value: []}

Output of tests on cmd

    ✔ Service should be created
LOG: 'getting into main thread'

LOG: 'getting into main thread'
LOG: 'getting into main thread'
LOG: 'getting into main thread'
LOG: 'Getting into filldatabase of 1service'
LOG: 'Getting into filldatabase of 1service'
LOG: 'Getting into filldatabase of 1service'
LOG: 'Getting into filldatabase of 1service'
LOG: 'push'
LOG: 'push'
LOG: 'push'
LOG: 'push'
LOG: ZoneAwarePromise{__zone_symbol__state: null, __zone_symbol__value: []}
LOG: ZoneAwarePromise{__zone_symbol__state: null, __zone_symbol__value: []}
LOG: ZoneAwarePromise{__zone_symbol__state: null, __zone_symbol__value: []}
LOG: ZoneAwarePromise{__zone_symbol__state: null, __zone_symbol__value: []}
.    ✔ function should return expectd json
// again file is just for sharing
31 10 2017 13:04:07.375:WARN [web-server]: 404: /assets/XML/<file>.json
LOG: 'Calling getJsonFromFile'

LOG: 'Calling getJsonFromFile'
LOG: 'Calling getJsonFromFile'
LOG: 'Calling getJsonFromFile'

Here is something weird as well. The Calling getJsonFromFile. is inside my app.component.ts. But i do not call this anywhere.

The function inside where the log is in is

getData() {
    this.databaseService.valueExist('checklistindex').then((data) => {
      if(!data) {
        console.log("Calling getJsonFromFile");
        this.indexService.getJsonfromFile().subscribe((data) => {

          console.log(JSON.stringify(data));
          this.indexService.filldatabase(data,'checklistindex' );
        })
      }
    })
  }

as you can see i do get all the way inside my fillPouch. However it does not return push. or anything what so ever along the line.


Solution

  • Solved this by mocking my dataservice the right way.

    databaseServiceMock

    import {DatabaseService} from "../../../../services/databaseService/databaseService";
    
    export class DatabaseServiceMock extends DatabaseService {
      constructor() {
        super(null);
      }
    
      fillPouch(json, key) {
        return Promise.resolve(true);
      }
    
      valueExist(key) {
        return Promise.resolve(true);
      }
    
      getIndexVersion(key) {
        return Promise.resolve("TRIAL VERSION v2");
      }
    
      }
    

    By mocking the databaseService i had to make some adjustments inside my TestBed as well.

    My beforeEach now

    beforeEach(async(() => {
    
        TestBed.configureTestingModule({
          imports: [HttpModule],
          providers: [
            {provide:DatabaseService, useClass: DatabaseServiceMock},
            IndexService,
            MockBackend,
            BaseRequestOptions,
            {
              provide: Http,
              useFactory: (backend, options) => new Http(backend, options),
              deps: [MockBackend, BaseRequestOptions]
            }
          ]
        });
        backend = TestBed.get(MockBackend);
    
        service = TestBed.get(IndexService);
      }));
    

    And my test looks like

    it('function should return expectd json', async(() => {
        service.filldatabase(inputJson, "testpouch").then((data) => {
          expect(data).toBeTruthy();
        })
      }));
    

    The issue of this question lies within this.db.put(json) cause of i did not mock my databaseService decent it did not go further here. i changed the fillPouch a bit to to make it easier to test.

    my fillPouch

    fillPouch(json, key) {
    json._id = key;
    return this.db.put(json).then(() => {
      return Promise.resolve(true);
    }).catch((error) => {
      return Promise.reject(false);
    });
    

    }

    This is all done with PouchDB