[英]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);
}));
});
我的兩個測試案例都失敗了:
(當密碼錯誤時,LoginComponent isError應該為true):預期未定義是真實的。
(應該調用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.