我正在对一个 Angular 应用程序进行单元测试,我需要模拟一个服务。我可以毫无问题地模拟服务方法,但是当我尝试以相同的方式模拟属性时,它给了我错误
我的配置服务有一个属性和一种方法,我想模拟该属性,因为我无法生成该值。
服务
@Injectable()
export class ConfigService {
public config = 'iamdirect';
constructor(private http: Http) {
}
public load(): Observable<any> {
return 'Iamokey';
}
}
Run Code Online (Sandbox Code Playgroud)
在角度测试中模拟服务
// mocking config service
configService = TestBed.get(ConfigService);
spyOn(configService, 'load')
.and.returnValue(Observable.of({
contactDetails: {
emailAddress: 'testemail@email.com'
}
}));
Run Code Online (Sandbox Code Playgroud)
当我这样做时,它给了我错误。
spyOn(configService, 'config') //config is the property
.and.returnValue(Observable.of({
contactDetails: {
emailAddress: 'testemail@email.com'
}
}));
Run Code Online (Sandbox Code Playgroud) 通过阅读此链接,我知道相当于
and.callFake是mockImplementation和
and.returnValue是mockReturnValue。
同样,and.callThrough()在 jest-preset-angular 中是否有等价物?
我有以下角度服务及其茉莉花测试。测试调用 f1() 并监视 f2()。函数 f2 接受变量 v2 并修改它(将字段 a 设置为 3)。函数 f2 应该用 v2 调用(如 f1 中声明的那样),但我的测试在toHaveBeenCalledWith 上失败,并说实际调用是在 f2 函数调用之后使用对象进行的。jasmine 是否在函数调用后匹配 .toHaveBeenCalledWith 的参数,这不应该是推荐的方式,或者我在这里犯了一些错误。
服务:
export class JasmineTestClass{
constructor(){
}
f2(v2){
v2.a = 3
};
f1(v1){
let v2 = {
a:30
};
this.f2(v2);
}
}
Run Code Online (Sandbox Code Playgroud)
测试:
describe('Test', () => {
let service: JasmineTestClass;
beforeEach(() => {
service = new JasmineTestClass();
spyOn(service, 'f2').and.callThrough();
});
let v1 = {
a:2, b:3
};
let v2 = {
a:30
};
it('should succeed', () …Run Code Online (Sandbox Code Playgroud) 嘿,我是 angular 6(又名 angular)测试的新手,我有一个问题,就是要重新评估迄今为止我看到的每一个测试。
我们先来看看简单组件的简单测试(由cli生成)
describe('CompComponent', () => {
let component: CompComponent;
let fixture: ComponentFixture<CompComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CompComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CompComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Run Code Online (Sandbox Code Playgroud)
我有一个主要问题:
1.我怎么知道每个 Async beforeEach 调用是在每个测试单元(又名它)之前完成的?是否有任何情况下此调用会在每个它之后发生,因为它毕竟是异步调用?
在我正在测试的类的 ngOnInit 方法中,我调用了一个重新运行可观察对象的服务函数。我已经为该服务实现了一个模拟,但我正在尝试使用间谍来完成这个确切的测试用例。根据我的理解,除非我在间谍上调用“.and.callThrough()”,否则间谍将覆盖模拟实现。问题是,尽管我为该函数设置了间谍,但每次模拟实现仍然会被执行。
我尝试将间谍移至 beforeEach 部分,但这没有帮助。我还尝试使用不带“.and.callFake()”扩展名的间谍。但这没有帮助。
规格.ts 文件:
fdescribe('AppComponent', () => {
let fixture;
let component;
let dataServiceMock: DataServiceMock;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent],
providers: [{ provide: DataService, useClass: DataServiceMock }],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
dataServiceMock = TestBed.get(DataService);
});
fit('should not show navigation if not logged in', async(() => {
spyOn(dataServiceMock,'getCurrentUser').and.callFake(() => {
console.log('IN CALL FAKE')
throwError(new Error('induced error'))
});
}));
Run Code Online (Sandbox Code Playgroud)
服务模拟的实现:
export class DataServiceMock {
currentUser: …Run Code Online (Sandbox Code Playgroud) 我有一个简单的组件,它使用一个返回 Observable 的服务。此类 Observable 用于通过 控制 html 元素的创建*ngIf。
这里的代码
@Component({
selector: 'hello',
template: `<h1 *ngIf="stuff$ | async as obj">Hello {{obj.name}}!</h1>`,
styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent implements AfterViewInit {
constructor(
private myService: MyService,
) {}
stuff$;
ngAfterViewInit() {
this.stuff$ = this.myService.getStuff();
}
}
@Injectable({
providedIn: 'root'
})
export class MyService {
getStuff() {
const stuff = {name: 'I am an object'};
return of(stuff).pipe(delay(100));
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,getStuff()返回和 Observable 带有 adelay并且一切都按预期工作。
现在我删除了 …
我有这个函数来检查password和confirmPassword字段是否具有相同的值。如果没有,该表格将被标记为invalid
confirmPasswordValidator(passwordGroupForm: AbstractControl){
let password = passwordGroupForm.get('password');
let confirmPassword = passwordGroupForm.get('confirmPassword');
console.log("password is "+password +"and confirmPassword is "+confirmPassword);
console.log("confirm password touched",confirmPassword.touched );
if(!confirmPassword.touched) return null ;//don't mark form invalid if the user hasn't interacted with confirmPassword field
else {
return (password.value === confirmPassword.value) ? null : {
confirmPasswordValidator: {
valid: false,
message: 'Password and Verify Password fields do not match'
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我编写了以下测试用例来检查该功能是否有效。
it('should not submit form if password and confirm password are …Run Code Online (Sandbox Code Playgroud) 我是 Angular 和 jhipster 的新手,我编辑了登录组件,添加了 formbuilder 和 MatDialogRef 并更新了单元测试:
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
/* Other imports */
@Component({
selector: 'jhi-login-modal',
templateUrl: './login.component.html',
styleUrls: ['login.scss']
})
export class JhiLoginModalComponent implements OnInit {
authenticationError: boolean;
hide = true;
loginForm: FormGroup;
constructor(
private readonly eventManager: JhiEventManager,
private readonly loginService: LoginService,
private readonly stateStorageService: StateStorageService,
private readonly router: Router,
private readonly fb: FormBuilder,
private readonly dialogRef: MatDialogRef<JhiLoginModalComponent>
) {}
ngOnInit(): void {
this.loginForm = …Run Code Online (Sandbox Code Playgroud) 我有一个带有输入的表单,并且有一个仅在表单数据更改时才需要启用的按钮。我正在使用原始检查,它在浏览器中都能正常工作,但我在测试它时遇到了麻烦。无论我做什么,无论我设置值多少次,原始检查总是正确的。知道我做错了什么吗?
HTML 有 2 个带有标签和按钮的输入
<form (ngSubmit)="login()"
[formGroup]="form">
<label>Email</label>
<input type="email" formControlName="email" name="email">
<label>Password</label>
<input type="password" formControlName="password">
<button type="submit">Login</button>
</form>
Run Code Online (Sandbox Code Playgroud)
我的打字稿文件
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
export class User {
constructor(public email: string,
public password: string) {
}
}
@Component({
selector: 'app-login-component',
templateUrl: './login-component.component.html',
styleUrls: ['./login-component.component.scss']
})
export class LoginComponentComponent implements OnInit {
@Output() loggedIn = new EventEmitter<User>();
form: FormGroup;
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.form = this.fb.group({
email: ['', …Run Code Online (Sandbox Code Playgroud) 我有几个组件(关于、服务、仪表板等),其中添加了标头组件。该应用程序运行良好。但是,我在测试时遇到错误。
\nimport { Component } from \'@angular/core\';\nimport { ComponentFixture, TestBed, waitForAsync } from \'@angular/core/testing\';\nimport { IonicModule } from \'@ionic/angular\';\nimport { SettingsPage } from \'./settings.page\';\n\ndescribe(\'SettingsPage\', () => {\n let component: SettingsPage;\n let fixture: ComponentFixture<SettingsPage>;\n\n beforeEach(waitForAsync(() => {\n TestBed.configureTestingModule({\n declarations: [ SettingsPage,MockHeaderComponent ],\n imports: [IonicModule.forRoot()]\n }).compileComponents();\n\n fixture = TestBed.createComponent(SettingsPage);\n component = fixture.componentInstance;\n fixture.detectChanges();\n }));\n\n it(\'should create\', () => {\n expect(component).toBeTruthy();\n });\n});\n@Component({\n selector: \'app-header\',\n template: \'\'\n})\nclass MockHeaderComponent {\n}\nRun Code Online (Sandbox Code Playgroud)\n第一个错误
\nChrome 93.0.4577.82 (Windows 10): Executed 22 of 26 (1 FAILED) (0 …Run Code Online (Sandbox Code Playgroud) angular-test ×10
angular ×8
jasmine ×4
testbed ×2
angular6 ×1
jhipster ×1
mocking ×1
rxjs ×1
typescript ×1