簡體   English   中英

Angular-cli Jasmine單元測試中如何監視方法

[英]How to spy method in angular-cli Jasmine unit testing

login.component.ts:

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  loginForm: FormGroup;
  email: AbstractControl;
  password: AbstractControl;
  isError: boolean;
  errorMessage: string;
  constructor(public loginService: LoginService, fb: FormBuilder, public router: Router, public helperService: HelperService) {
    this.loginForm = fb.group({
      'email': ['', Validators.compose([Validators.required, Validators.email, Validators.minLength(4), Validators.maxLength(50)])
      ],
      'password': ['', Validators.compose([Validators.required, AppValidator.digitsOnly, Validators.minLength(4), Validators.maxLength(50)])
      ]
    });
  }
    this.email = this.loginForm.controls['email'];
this.password = this.loginForm.controls['password'];
  ngOnInit() { }

  onLogin(loginForm: LoginForm): void {
    this.isError = false;
    if (this.loginForm.valid) {
      // if email='test@gmail.com'& password='123456', login will success else it will fail.
      this.loginService.fakeLogin(loginForm)
        .subscribe((res: LoginResponse) => {
          const url = '/dashboard';
          this.router.navigate([url]);
        },
        (err: ErrorResponse) => {
          this.errorMessage = err.message;
          this.isError = true;
        });
    }
  }
}

login.component.html:

<div class="login">
    <h1>Login</h1>
    <p *ngIf="isError">
        <ngb-alert [type]="'danger'" [dismissible]="true" (close)="closeAlert()">{{ errorMessage }}</ngb-alert>
    </p>
    <form method="post" [formGroup]="loginForm" (ngSubmit)="onLogin(loginForm.value)">
        <div class="form-group row" [ngClass]="helperService.getInputValidationClass(loginForm,'email')">
            <div class="col-sm-12">
                <input [formControl]="email" type="text" class="form-control" id="email" placeholder="Email">
                <span *ngIf="helperService.showCtrlValidationMsg(loginForm,'email')" class="help-block sub-little-text text-danger">{{helperService.getCtrlValidationMsg(loginForm,'email')}}</span>
            </div>
        </div>
        <div class="form-group row" [ngClass]="helperService.getInputValidationClass(form,'password')">
            <div class="col-sm-12">
                <input [formControl]="password" type="password" class="form-control" id="password" placeholder="Password">
                <span *ngIf="helperService.showCtrlValidationMsg(loginForm,'password')" class="help-block sub-little-text text-danger">{{helperService.getCtrlValidationMsg(loginForm,'password')}}</span>
            </div>
        </div>
        <button type="submit" [disabled]="helperService.isFormSubmitDisabled(loginForm,helperService.isProcessing)" class="btn btn-primary btn-block btn-large login-submit">
          <span >Sign in</span><span *ngIf="helperService.isProcessing">Processing...<i class="fa fa-spinner fa-spin fa-fw" aria-hidden="true"></i></span>
        </button>
    </form>
</div>

login.component.spec.ts:

import { By } from '@angular/platform-browser';
import { LoginService } from './login.service';
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SlimLoadingBarModule } from 'ng2-slim-loading-bar';
import { SlimLoadingBarService } from 'ng2-slim-loading-bar';
import { RouterTestingModule } from '@angular/router/testing';

import { LoginComponent } from './login.component';
import { HelperService } from '../shared/helper.service';
import { NgbAlertModule } from '@ng-bootstrap/ng-bootstrap/alert/alert.module';
import { NgbAlertConfig } from '@ng-bootstrap/ng-bootstrap/alert/alert-config';

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [FormsModule, ReactiveFormsModule, RouterTestingModule, NgbAlertModule,],
      declarations: [LoginComponent],
      providers: [LoginService, HelperService, NgbAlertConfig,],
    }).compileComponents();
  }));

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

  function updateForm(loginFormValue) {
    component.loginForm.controls['email'].setValue(loginFormValue.email);
    component.loginForm.controls['password'].setValue(loginFormValue.password);
  }    

  it('isError should be true when password is wrong', fakeAsync(() => {
    const loginFormValue = {
      email: 'test@gmail.com',
      password: '123', // give wrong password
    };
    updateForm(loginFormValue);
    fixture.debugElement.query(By.css('.login-submit')).triggerEventHandler('ngSubmit', null);
    tick(); // wait for async operations
    expect(component.isError).toBeTruthy();
  }));

  it('onLogin should be called', fakeAsync(() => {
    spyOn(component, 'onLogin');
    const loginFormValue = {
      email: 'test@gmail.com',
      password: '123456',
    };
    updateForm(loginFormValue);
    fixture.debugElement.query(By.css('.login-submit')).triggerEventHandler('ngSubmit', null);
    expect(component.onLogin).toHaveBeenCalledWith(loginFormValue);
  }));
});

我的兩個測試案例都失敗了:

  1. (當密碼錯誤時,LoginComponent isError應該為true):預期未定義是真實的。

  2. (應該調用LoginComponent onLogin):預期的間諜onLogin已使用[Object({email:'test@gmail.com',password:'12345'})]調用,但從未被調用過。

我在這里到底在做什么錯?

您的兩個結果均顯示未調用onLogin。 我懷疑這條線不起作用:

fixture.debugElement.query(By.css('.login-submit')).triggerEventHandler('ngSubmit', null);

我會用:

fixture.debugElement.query(By.css('.login-submit')).click();

觸發ngSubmit事件的另一種方法可能是:

fixture.debugElement.query(By.css('.login-submit')).dispatchEvent(new Event('ngSubmit'));

盡管我還沒有嘗試使用ngSubmit事件,但是它可以與其他事件一起使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM