Angular unit testing form validation

I’m learning angular 8 and I’m using Karma for unit testing. I have created a basic registration form which works correctly but I’m facing issues in testing.

Upon testing I’m getting 2 failures

RegisterComponent > form should be valid
Error: Expected validator to return Promise or Observable.

and

RegisterComponent > should call onSubmit method
Error: <toHaveBeenCalledTimes> : Expected a spy, but got FormGroup({ validator: Function, asyncValidator: null, _onCollectionChange: Function, pristine: true, touched: false, _onDisabledChange: [  ], controls: Object({ name: FormControl({ validator: Function, asyncValidator: null, _onCollectionChange: Function, pristine: true, touched: false, _onDisabledChange: [ Function ], _onChange: [ Function ], _pendingValue: '', value: '', status: 'INVALID', errors: Object({ required: true }), valueChanges: EventEmitter({ _isScalar: false, observers: [  ], closed: false, isStopped: false, hasError: false, thrownError: null, __isAsync: false }), statusChanges: EventEmitter({ _isScalar: false, observers: [  ], closed: false, isStopped: false, hasError: false, thrownError: null, __isAsync: false }), _parent: <circular reference: Object> }), email: FormControl({ validator: Function, asyncValidator: Function, _onCollectionChange: Function, pristine: true, touched: false, _onDisabledChange: [ Function ], _onChange: [ Function ], _pendingValue: '', value: '' ....
Usage: expect(<spyObj>).toHaveBeenCalledTimes(<Number>)

register.component.ts

    import { ActivatedRoute, Router } from '@angular/router';
    import { Component, OnInit } from '@angular/core';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';

    import { AuthenticationService } from '@/_services';
    import { MustMatch } from '@/_helpers/validators';

    @Component({
      selector: 'app-register',
      templateUrl: './register.component.html',
      styleUrls: ['./register.component.scss']
    })
    @Component({ templateUrl: 'register.component.html' })
    export class RegisterComponent implements OnInit {
      registerForm: FormGroup;
      submitted = false;
      returnUrl: string;
      error = '';

      constructor(
        private formBuilder: FormBuilder,
        private route: ActivatedRoute,
        private router: Router,
        private authenticationService: AuthenticationService
      ) {
        if (this.authenticationService.currentUserValue) {
          this.router.navigate(['/']);
        }
      }

      ngOnInit() {
        this.registerForm = this.formBuilder.group({
          name: ['', Validators.required],
          email: ['', Validators.required, Validators.email],
          phone: ['', Validators.required],
          password: ['', Validators.required, Validators.minLength(6)],
          confirmPassword: ['', Validators.required],
        }, {
            validator: MustMatch('password', 'confirmPassword')
          });

        this.returnUrl = this.route.snapshot.queryParams.returnUrl || '/';
      }

      get f() {
        return this.registerForm.controls;
      }

      onSubmit() {
        this.submitted = true;
        if (this.registerForm.invalid) {
         return;
        }

        this.submitted = false;
      }
    }


register.component.spec.ts
--------------------------

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { RegisterComponent } from './register.component';
import { ActivatedRoute, Router } from '@angular/router';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { DebugElement } from '@angular/core';

describe('RegisterComponent', () => {
    let component: RegisterComponent;
    let fixture: ComponentFixture<RegisterComponent>;
    let de: DebugElement;
    let el: HTMLElement;
    const fakeActivatedRoute = {
        snapshot: {
            queryParams: {
                returnUrl: '/'
            }
        }
    };
    const routerSpy = jasmine.createSpyObj('Router', ['navigate']);

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [ReactiveFormsModule, FormsModule, HttpClientTestingModule],
            declarations: [RegisterComponent],
            providers: [
                { provide: Router, useValue: routerSpy },
                { provide: ActivatedRoute, useFactory: () => fakeActivatedRoute }
            ]

        }).compileComponents().then(() => {
            fixture = TestBed.createComponent(RegisterComponent);
            component = fixture.componentInstance;
            component.ngOnInit();
            fixture.detectChanges();
            de = fixture.debugElement.query(By.css('form'));
            el = de.nativeElement;
        });
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(RegisterComponent);
        component = fixture.componentInstance;
        component.ngOnInit();
        fixture.detectChanges();
    });

    it('form invalid when empty', () => {
        component.registerForm.controls.name.setValue('');
        component.registerForm.controls.email.setValue('');
        component.registerForm.controls.phone.setValue('');
        component.registerForm.controls.password.setValue('');
        component.registerForm.controls.confirmPassword.setValue('');
        expect(component.registerForm.valid).toBeFalsy();
    });

    it('username field validity', () => {
        const name = component.registerForm.controls.name;
        expect(name.valid).toBeFalsy();

        name.setValue('');
        expect(name.hasError('required')).toBeTruthy();

    });

    it('email field validity', () => {
        const email = component.registerForm.controls.email;
        expect(email.valid).toBeFalsy();

        email.setValue('');
        expect(email.hasError('required')).toBeTruthy();
    });

    it('phone field validity', () => {
        const phone = component.registerForm.controls.phone;
        expect(phone.valid).toBeFalsy();

        phone.setValue('');
        expect(phone.hasError('required')).toBeTruthy();

    });

    it('password field validity', () => {
        const password = component.registerForm.controls.password;
        expect(password.valid).toBeFalsy();

        password.setValue('');
        expect(password.hasError('required')).toBeTruthy();

    });

    it('confirmPassword field validity', () => {
        const confirmPassword = component.registerForm.controls.confirmPassword;
        expect(confirmPassword.valid).toBeFalsy();

        confirmPassword.setValue('');
        expect(confirmPassword.hasError('required')).toBeTruthy();

    });

    it('should set submitted to true', () => {
        component.onSubmit();
        expect(component.submitted).toBeTruthy();
    });

    it('should call onSubmit method', () => {
        spyOn(component, 'onSubmit');
        el = fixture.debugElement.query(By.css('button')).nativeElement;
        el.click();
        expect(component.registerForm).toHaveBeenCalledTimes(1);
    });

    it('form should be valid', () => {
        component.registerForm.controls.name.setValue('sasd');
        component.registerForm.controls.email.setValue('[email protected]');
        component.registerForm.controls.phone.setValue('132456789');
        component.registerForm.controls.password.setValue('qwerty');
        component.registerForm.controls.confirmPassword.setValue('qwerty');
        expect(component.registerForm.valid).toBeTruthy();
    });
});

I can’t seem to understand what is causing this issue. Have gone through several docs and tutorials for this but it doesn’t seem to work.

Source: New feed
Source Url Angular unit testing form validation