我创建了一个项目,它包含一个返回承诺布尔响应的服务。因此,我编写了规范代码来测试代码及其下降。错误如下,
预期“是”为“否”。
请帮助我确定我在测试承诺响应时所做的问题?。
代码示例如下。
服务
@Injectable({
providedIn: "root"
})
export class CustomerService {
constructor() {}
isValid() : Promise<boolean> {
return Promise.resolve(true);
}
}
组件
@Component({
selector: 'app-customer',
templateUrl: './customer.component.html',
styleUrls: ['./customer.component.scss']
})
export class CustomerComponent implements OnInit {
icon = new BehaviorSubject('yes');
constructor(private readonly customerService : CustomerService) {
}
ngOnInit(): void {
this.customerService.isValid().then(isValid => {
if(isValid){
this.icon.next('yes');
} else{
this.icon.next('no');
}
});
}
}
测试组件
describe('CustomerComponent', () => {
let component: CustomerComponent;
let fixture: ComponentFixture<CustomerComponent>;
let customerServiceSpy: jasmine.SpyObj<CustomerService>;
beforeEach(async () => {
customerServiceSpy = jasmine.createSpyObj<CustomerService>(['isValid']);
await TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
],
declarations: [
CustomerComponent,
],
providers: [
{ provide: CustomerService, useValue: customerServiceSpy },
]
}).compileComponents();
fixture = TestBed.createComponent(CustomerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
fit('should change initial value of icon according to the response of isValid function', waitForAsync(() => {
fixture.detectChanges();
customerServiceSpy.isValid.and.returnValue(Promise.resolve(false));
component.ngOnInit();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(component.icon.value).toBe('no');
});
customerServiceSpy.isValid.and.returnValue(Promise.resolve(true));
component.ngOnInit();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(component.icon.value).toBe('yes');
});
}));
});
将两个期望放到自己的测试中。 expect 在一个 promise 中,所以第二个间谍在运行 promise 中的代码之前运行。或者不是把你的期望放在承诺回调中,而是做
await fixture.whenStable();
所以所有代码都在承诺解决后运行。
const fixture = { whenStable: () => Promise.resolve(true) };
describe('promise', function() {
let customerServiceSpy = jasmine.createSpyObj(['isValid']);
it('fail', async () => {
customerServiceSpy.isValid.and.returnValue(Promise.resolve('no'));
fixture.whenStable().then(() => {
// this code is running in a promise so it is queued to run after this whole block
customerServiceSpy.isValid().then(isValid => { expect(isValid).toEqual('no'); })
});
// this runs before the code in the promise runs so overwrites the initial spy
customerServiceSpy.isValid.and.returnValue(Promise.resolve('yes'));
});
it('pass', async () => {
customerServiceSpy.isValid.and.returnValue(Promise.resolve('no'));
fixture.whenStable().then(() => {
customerServiceSpy.isValid().then(isValid => { expect(isValid).toEqual('no'); })
});
});
it('pass with await', async () => {
customerServiceSpy.isValid.and.returnValue(Promise.resolve('no'));
await fixture.whenStable();
// Promise has reolved so isValid still returns the no promise
customerServiceSpy.isValid().then(isValid => { expect(isValid).toEqual('no'); })
customerServiceSpy.isValid.and.returnValue(Promise.resolve('yes'));
});
});
.snippet-result-code {
height: 320px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/4.5.0/jasmine.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/4.5.0/jasmine-html.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/4.5.0/boot0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/4.5.0/boot1.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/4.5.0/jasmine.min.css" />