RasMason
RasMason

Reputation: 2212

service undefined jasmine test

testing a component that needs to subscribe to a service, but the jasmine test always fails

I log the service to the console and use expect(contactService).toBeDefined() which returns success

But as soon as I subscribe it returns undefined

spec:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ContactComponent } from './contact.component';
import { DivPositionsService } from '../../../services/div-positions.service';
import { ContactService } from '../../../services/contact.service';
import { HttpClientModule } from '@angular/common/http';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Email } from '../../../models/email.model';
import { HttpClientTestingModule, HttpTestingController } from '../../../../../node_modules/@angular/common/http/testing';
describe('ContactComponent', () => {
  let component: ContactComponent;
  let fixture: ComponentFixture<ContactComponent>;
  let contactService;
  let httpMock: HttpTestingController;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ContactComponent ],
      imports:[
        FormsModule, 
        ReactiveFormsModule, 
        HttpClientModule, HttpClientTestingModule],
      providers:[
        {
          provide: ContactService,
          useValue: jasmine.createSpyObj('contactService', ['sendMail'])
        },
        {
        provide: DivPositionsService,
        useValue: jasmine.createSpyObj('divPositionsService', ['updateObj'])
      }],
      schemas: [NO_ERRORS_SCHEMA]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ContactComponent);
    component = fixture.componentInstance;
    contactService = TestBed.get(ContactService);
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should create form ngOnInit', () => {
    component.ngOnInit()
    expect(component.contactForm).toBeDefined();
  });
  it('should submit values from form', () => {
    const successMsg = {sucess: true, msg: 'sent'}
    const contact:Email = {
    name:'Test name',
    email: 'Test email',
    message: 'Test message',
    phone: 'Test phone'
    }
    console.log(contactService)
    expect(contactService).toBeDefined()
    contactService.sendMail(contact)
    .subscribe(results => {
      // expect(results).toBeDefined();
      //has to be what is returned by the function
      console.log(results)
      expect(results).toEqual(successMsg);


    });
    console.log(contactService)
  });

});

Upvotes: 2

Views: 6018

Answers (2)

lupa
lupa

Reputation: 527

First, you spy on the contactService, which following the code you provide, not be defined in anywhere.
And you should define your contactSevice before the compileComponents() function being executed.

so you should doing something like this.

TestBed.configureTestingModule({
  declarations: [ ContactComponent ],
  imports:[
    FormsModule, 
    ReactiveFormsModule, 
    HttpClientModule, HttpClientTestingModule],
  providers:[
    ...,
    {
    provide: ContactService,
    useValue: class {
      sendMail: () => of({//what ever object you want to return here});
    }
  }],
  schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();

But the approach above make your mock service function called and you can't actually spy on it
If you need to spy on that and do whatever you want with mock service

You could implement a mock class like this:

class MockContactService {
  sendMail() {
    return of({});
  }
}

let mockContactService;

beforeEach(()=> {
  mockContactService = new MockContactService();
  TestBed.configureTestingModule({
     ...,
     providers:[
       {
         provide: ContactService,
         useValue: mockContactService,
     }],...
  })
  .compileComponents();

  it('what ever', () => {
    spyOn(mockContactService, 'sendMail');
  })
})

Upvotes: 1

Castro Roy
Castro Roy

Reputation: 7803

Before your call to contactService.sendMail(contact), you should mock the return value of sendMail, something like this.

contactService.sendMail.and.returnValue(Observable.of(successMsg));

Hope it helps

Upvotes: 2

Related Questions