我的一个测试文件中出现错误,尝试启动Karma运行程序时出现以下错误:
Error: Uncaught (in promise): TypeError: locale.toLowerCase is not a function
at <Jasmine>
at resolvePromise (node_modules/zone.js/dist/zone.js:814:31)
at node_modules/zone.js/dist/zone.js:877:17
at ZoneDelegate.invokeTask (node_modules/zone.js/dist/zone.js:421:31)
at AsyncTestZoneSpec.onInvokeTask (node_modules/zone.js/dist/async-test.js:90:25)
我不知道为什么会这样,并且一直在努力解决这个问题。这是被测组件。如您所见,我正在使用一个名为NgxSmartModal的外部软件包:
import { Component, Inject, LOCALE_ID, OnDestroy, OnInit } from "@angular/core";
import { formatCurrency } from "@angular/common";
interface SecciItemInterface {
name: string,
content: string
}
@Component({
selector: "secci-modal",
templateUrl: "migration/app/pages/payment-page/sub-sections/secci-modal/secci-modal.component.html"
})
/**
* Display the SECCI direct debit modal
**/
export class SecciModal implements OnInit, OnDestroy {
public totalAncillariesTax: number = 0;
public ancillaries = [];
public interestRate: any;
constructor(
@Inject("Brand") private Brand,
@Inject("Quote") private Quote,
@Inject("Api") private Api,
@Inject("Global") private Global,
@Inject("Page") private Page,
@Inject(LOCALE_ID) private _locale: string
) {
}
public ngOnInit(): void {
this.getInterestRate();
this.ancillaries = this.secciAncillaries();
}
/**
* Sets the ancillaries that are to be displayed in the modal
*
* @returns {Array<Object>}
*/
public secciAncillaries(): Array<Object> {
const ancDisplayList = [];
if (this.Quote.cars) {
if (this.Quote.ancillaries !== 'undefined' && this.Quote.ancillaries !== null) {
const secciSelectedList = JSON.parse(JSON.stringify(this.Quote.ancillaries.selected));
const secciAvailableList = JSON.parse(JSON.stringify(this.Quote.ancillaries.available));
if (this.Quote.haveComprehensive) {
secciSelectedList.PMWindscreenUpgradeCov = true;
secciAvailableList.PMWindscreenUpgradeCov = {
"single" : {
"total" : 0
},
"name" : "Windscreen Cover"
};
}
let ncbProtectionTotal = 0;
let ncbProtectionTax = 0;
let ncbGuaranteeTotal = 0;
let ncbGuaranteeTax = 0;
for (let car in this.Quote.cars) {
if (this.Quote.cars[car].ancillaries){
if (this.Quote.cars[car].ancillaries.selected["PMNCBProtectionCov"]) {
ncbProtectionTotal += this.Quote.cars[car].ancillaries.selected["PMNCBProtectionCov"].price;
ncbProtectionTax += this.Quote.cars[car].ancillaries.selected["PMNCBProtectionCov"].taxAmount;
}
if (this.Quote.cars[car].ancillaries.selected["PMNCBGuaranteedCov"]) {
ncbGuaranteeTotal += this.Quote.cars[car].ancillaries.selected["PMNCBGuaranteedCov"].price;
ncbGuaranteeTax += this.Quote.cars[car].ancillaries.selected["PMNCBGuaranteedCov"].taxAmount;
}
}
}
const ncbProtection = {"content" : formatCurrency(ncbProtectionTotal, this._locale, "£", "GBP"), "name" : "Protected No Claims Bonus"};
const ncbGuarantee = {"content" : formatCurrency(ncbProtectionTotal, this._locale, "£", "GBP"), "name" : "Guaranteed No Claims Bonus"};
for (let anc in secciSelectedList) {
if (secciSelectedList[anc]) {
let content: string;
if (secciAvailableList[anc].single.total == 0) {
content = "Included";
}
else {
content = formatCurrency(secciAvailableList[anc].single.total, this._locale, "£", "GBP");
this.totalAncillariesTax += secciAvailableList[anc].single.tax;
}
const obj: SecciItemInterface = {
name: secciAvailableList[anc].name,
content
};
ancDisplayList.push(obj);
}
}
if (ncbProtectionTotal > 0){
this.totalAncillariesTax += ncbProtectionTax;
ancDisplayList.push(ncbProtection);
}
if (ncbGuaranteeTotal > 0){
this.totalAncillariesTax += ncbGuaranteeTax;
ancDisplayList.push(ncbGuarantee);
}
}
}
if (this.Quote.home){
if (this.Quote.home.ancillaries !== 'undefined' && this.Quote.home.ancillaries !== null) {
const secciSelectedList = JSON.parse(JSON.stringify(this.Quote.ancillaries.selected));
const secciAvailableList = JSON.parse(JSON.stringify(this.Quote.ancillaries.available));
for (let anc in secciSelectedList){
if (secciSelectedList[anc]){
const obj: SecciItemInterface = {
name: secciAvailableList[anc].name,
content: formatCurrency(secciAvailableList[anc].single.total, this._locale, "£", "GBP")
};
this.totalAncillariesTax += secciAvailableList[anc].single.tax;
ancDisplayList.push(obj);
}
}
}
}
return ancDisplayList;
}
public getInterestRate(): any {
const proratedPremium = this.Quote.response.quotePolicyTerm.proratedPremium;
this.interestRate = ((proratedPremium !== "undefined" && proratedPremium !== null) && (proratedPremium.monthlyPremium)) ? proratedPremium.monthlyPremium.interest : "ERROR";
}
public ngOnDestroy(): void {
}
private modalHeight() {
}
}
以及规格文件:
import { TestBed, ComponentFixture, async, inject } from "@angular/core/testing";
import { SecciModal } from "./secci-modal.component";
import {NgxSmartModalModule, NgxSmartModalService} from "ngx-smart-modal";
import { LOCALE_ID } from "@angular/core";
fdescribe("Secci Modal component", () => {
let fixture: ComponentFixture<SecciModal>;
let component: SecciModal;
let mockBrand = {
name: "name",
ddRejectionFee: 0,
preCollectionAdminFee: 0,
postCollectionAdminFee: 0
};
let mockQuote = {
policy: {
monthly: {
deposit: 0,
numberOfPayments: 0,
totalPremium: 0,
installmentCharges: 0,
apr: 0,
},
singleDirectDebitCost: 0,
singleDirectDebitTax: 0
},
daysOfCover: 0,
haveComprehensive: true,
ancillaries: {
selected: {
PMWindscreenUpgradeCov: true
},
available: {
}
},
cars: [
{
ancillaries: {
selected: {
PMNCBProtectionCov: {
price: 0,
taxAmount: 0
},
PMNCBGuaranteedCov: {
price: 0,
taxAmount: 0
}
}
}
}
],
home: {
ancillaries: {
selected: {
},
available: {
}
}
},
response: {
quotePolicyTerm: {
proratedPremium: {
monthlyPremium: {
interest: 0
}
}
}
}
};
let mockApi = {
};
let mockGlobal = {
};
let mockPage = {
};
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
SecciModal
],
imports: [
NgxSmartModalModule.forRoot()
],
providers: [
{
provide: "Brand",
useValue: mockBrand
},
{
provide: "Quote",
useValue: mockQuote
},
{
provide: "Api",
useValue: mockApi
},
{
provide: "Global",
useValue: mockGlobal
},
{
provide: "Page",
useValue: mockPage
},
{
provide: LOCALE_ID,
useValue: {}
}
]
})
.compileComponents()
.then(() => {
// create component and test fixture
fixture = TestBed.createComponent(SecciModal);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it("secciAncillaries", (done) => {
expect(true).toBeTruthy();
done();
});
});
正如我所说,我真的无法提供任何进一步的信息,因为我不知道为什么会发生这种情况,并且以前从未收到此错误!任何帮助将是一个加号。 谢谢
答案 0 :(得分:0)
您可能需要为NgxSmartModal
导入一个Stub文件来伪造方法,因为在单元测试中,并没有真正“创建”模态。我们也遇到了类似的问题,Stub似乎可以解决该问题。我认为将其包含在库中以方便单元测试可能很有用。
使用此存根(我们用来伪造库的存根):
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
export class NgxSmartModalServiceStub {
getModal(id) {
return {
open: function () {
return;
},
close: function () {
return;
},
isVisible: function () {
return;
},
onOpen: Observable.of({}),
onAnyCloseEvent: Observable.of({})
};
}
get(id) {
return {
open: function () {
return;
},
close: function () {
return;
},
isVisible: function () {
return;
},
onOpen: Observable.of({}),
onAnyCloseEvent: Observable.of({
removeData() {
return;
}
})
};
}
setModalData() {
return;
}
open() {
return;
}
getModalStackCount() {
return;
}
addModal() {
return;
}
}
然后像这样在您的规范文件中使用它:
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule,
...
],
providers: [
{ provide: NgxSmartModalService, useClass: NgxSmartModalServiceStub }
],
}).compileComponents();
}));
通过这种方式,您可以spyOn(...)
在组件,服务等中可能使用的库方法...