Home > Net >  Unit Test Error when having CookieService as argument in constructor of tested component
Unit Test Error when having CookieService as argument in constructor of tested component

Time:06-09

I would like to test a function. To call that function in unit test I need to create an instance of the component class. The component class contains different services as arguments in the constructor including the service CookieService. The service depends on the third-library 'ngx-cookie' which has setters and getters.

I tried to mock the service to be able to create an instance of the component class like this:

import {CookieService} from "ngx-cookie-service";
....
    
 beforeEach(async(() => {
            const mockedFormBuilder = jasmine.createSpyObj('FormBuilder', ['control', 'array', 'group']);
            
            const get = function get(name: string): string {
            
                return 'test...';
            };

    TestBed.configureTestingModule({
                declarations: [HelloWorldComponent,...],
                imports: [
                    ...    
                ],
                providers: [
                    {provide: FormBuilder, useValue: mockedFormBuilder},
                    {provide: CookieService, useValue: get('name')},
                ]
    
            })
                .compileComponents();
    
        }));

describe('getArr', () => {

    it('should return array', () => {

        const text = '[email protected]';
        const textArr = ['[email protected]']

        let getArr: string[];


        // @ts-ignore
        getArr = new HelloWorldComponent(FormBuilder,CookieService).getTextArray(tex);

        expect(getArr).toBe(textArr);
    })
})

Following error appears when running the test:

TypeError: this.cookieService.get is not a function
    at <Jasmine>
    at new HelloWorldComponent(http://localhost:9876/_karma_webpack_/src/app/helloworld.component.ts:63:51)
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/src/app/helloworld.component.spec.ts:113:28)
    at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:359:1)
    at ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:308:1)
    at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:358:1)
    at Zone.run (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:124:1)
    at runInTestZone (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:561:1)
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:576:1)

This is how the ComponentClass looks like:

export class HelloWorldComponent {
   constructor(private fb: FormBuilder, private cookieService:CookieService){
     const cookie:string=this.cookieService.get('somename')
   }
}

I understand that the cookieService has no function but a getter and setter, but I do not quite get how to mock the getter and how to correctly insert it in providers

Does someone came accross the same error when testing and how did you solved it?

Any help would be very appreciated!


Update: Use Stub Service

export class CookieServiceStub{
    cookie:string= 'gdhjgsfgsjdfg';
    get (name:string):string{
        return this.cookie;
    }
}

In Spec file: ...

TestBed.configureTestingModule({
                declarations: [HelloWorldComponent,...],
                imports: [
                    ...    
                ],
                providers: [
                    {provide: FormBuilder, useValue: mockedFormBuilder},
                    {provide: CookieService, useClass:CookieServiceStub},
                ]

            })
                .compileComponents();

        }));

CodePudding user response:

You are currently providing the result of the call get('name') as the value of your CookieService service. I think this is incorrect... here:

{provide: CookieService, useValue: get('name')}

It is a little easier to create a Stub Class in this case:

first figure in your component the functions you are calling from the service, then create a Stub Class for it:

class CookieServiceStub{
  get(name: string) {
    return 'your value'
  }

  secondFunction() {} 
  // add as many as necessary
}

Then you can replace your provision of the CookieService with your stub class:

{provide: CookieService, useClass: CookieServiceStub}

CodePudding user response:

jasmine.createSpyObj is used to create mocks that will spy on methods. It will return an object for each property defined in the spy.

You can create a mockCookieService and add the get method

mockCookieService = jasmine.createSpyObj('CookieService', ['get']);

Try like this:

describe('Service: ', () => {

  let mockCookieService;

  beforeEach(() => {
    mockCookieService = jasmine.createSpyObj('CookieService', ['get']);

    TestBed.configureTestingModule({
      imports: [
          ...
      ],
      providers: [
        { provide: CookieService, useValue: mockCookieService },
      ]
    });

  });

You can refer this article

  • Related