angular - 如何在 Angular Jest 中编写单元测试和模拟 httpClient
问题描述
我想在 Jest 中为以下 http 函数调用编写一个单元测试:
this.httpClient.post(this.urlService.baseRestEndpoint + '/ast/getDeviceSearch', filterData).subscribe(
(response:any) => {
console.log('response',response)
if(response.DeviceReply.ReturnCode===0){
if(filterData.subSystemType==="0"){
this.dbOnly=false;
if (response.DeviceReply.TotalDevices > 3200) {
this.count = "3200 out of "+ response.DeviceReply.TotalDevices +" devices";
} else {
this.count = response.DeviceReply.TotalDevices;
}
}
let deviceArray=[];
//for db configuration response
if(_.isUndefined(response.DeviceReply.ReplyNode)){
if(Array.isArray(response.DeviceReply)) {
deviceArray = response.DeviceReply;
}else{
deviceArray = [response.DeviceReply];
}
}else{
deviceArray = response.DeviceReply.ReplyNode;
}
//filter with register device
const responseDeviceList = _.filter(deviceArray,{"ReturnCode" : 0});
// check register device
if(responseDeviceList.length>0){
//concat device in one array
let devices = [];
responseDeviceList.forEach((deviceList) =>{
// checking if response does not have node name
if(!_.isUndefined(deviceList.Name)) {
// checking if device is array or object and appending node name in device array
if (Array.isArray(deviceList.Device)) {
_.map(deviceList.Device, function (objectResult) {
objectResult['Node'] = deviceList.Name;
});
} else {
deviceList.Device['Node'] = deviceList.Name;
}
}
//concatenate device array
devices=_.concat(devices,deviceList.Device);
});
if(devices.length>0){
this.deviceModelValue.filter(a => {
devices.map(b => {
if(a.Id == b.Model) {
b.Model = a.Name
}
})
});
devices.map(b => {
if(isNaN(Number(b.TimeStamp)))
{
b.Duration = b.TimeStamp;
this.removeHeaderList.push('TimeStamp');
}
else if(b.TimeStamp === '' && this.selectedSearch === 'SIP Trunk') {
b.Duration = 'N/A';
this.removeHeaderList.push('TimeStamp');
}
else if(b.TimeStamp === '' && this.selectedSearch !== 'SIP Trunk') {
b.TimeStamp = 'N/A';
}
else {
b.TimeStamp = moment.utc(b.TimeStamp * 1000).local().format('dddd, MMMM Do, YYYY, h:mm:ss A')
}
if(this.selectedSearch === 'Phone' || this.selectedSearch === '')
{
b.DirectoryNumber = b.DirNumber.split('-')[0];
b.ActiveLoadId = b.LoadId;
["Description", "LoginUserId", "DownloadServer", "DownloadFailureReason", "DownloadStatus", "RequestedLoadId", "InactiveLoadId"].forEach(val => b[val] ||= 'N/A')
}
["StatusReason", "Ipv6Address"].forEach(val => b[val] ||= 'N/A')
//Status Reason
switch(b.StatusReason){
case 0: {b.StatusReason = "AllFine" ; break;}
case 1: {b.StatusReason = "Unknown" ; break;}
case 2: {b.StatusReason = "NoEntryInDatabase" ; break;}
case 3: {b.StatusReason = "DatabaseConfigurationError" ; break;}
case 4: {b.StatusReason = "DeviceNameUnresolveable" ; break;}
case 5: {b.StatusReason = "MaxDevRegExceeded" ; break;}
case 6: {b.StatusReason = "ConnectivityError" ; break;}
case 7: {b.StatusReason = "InitializationError" ; break;}
case 8: {b.StatusReason = "DeviceInitiatedReset" ; break;}
case 9: {b.StatusReason = "CallManagerReset" ; break;}
case 10: {b.StatusReason = "AuthenticationError" ; break;}
case 11: {b.StatusReason = "InvalidX509NameInCertificate" ; break;}
case 12: {b.StatusReason = "InvalidTLSCipher" ; break;}
case 13: {b.StatusReason = "DirectoryNumberMismatch" ; break;}
case 14: {b.StatusReason = "MalformedRegisterMsg" ; break;}
case 15: {b.StatusReason = "ProtocolMismatch" ; break;}
case 16: {b.StatusReason = "DuplicateRegistration" ; break;}
case 17: {b.StatusReason = "AuthenticatedDeviceAlreadyExists" ; break;}
}
//Protocol Mapping
if(b.Protocol == 1) {
b.Protocol = "SCCP"
}
else if(b.Protocol == 2) {
b.Protocol = "SIP"
}
if(this.selectedSearch === 'H323 Devices') {
["Status", "Node", "IpAddress", "StatusReason"].forEach(val => b[val] ||= 'N/A');
this.removeHeaderList.push('Ipv6Address');
}
})
this.getHeaderAndData(devices);
}else{
this.isLoading = false;
this.goBackgtoSearchPage();
}
}else{
this.alertService.error('Warning!', 'Error getting search result', this.alertConfig);;
this.isLoading = false;
this.goBackgtoSearchPage();
}
}else{
// get 0 device
this.alertService.error('Warning', '0 Device(s) Found', this.alertConfig);
this.isLoading = false;
this.goBackgtoSearchPage();
}
},
(error) => {
this.alertService.error('Error', 'Internal error occurred', this.alertConfig);
this.isLoading = false;
this.goBackgtoSearchPage();
});
使用的变量 hare 具有以下数据:
this.urlService.baseRestEndpoint = http://localhost:4200/webrtmt/rest;
filterData = { dnldStatus: "",
maxDevices: "200",
model: "",
nodeName: "",
protocol: "Any",
searchPattern: "",
searchType: "",
status: "",
subSystemType: "0",
type: "6" ,
}
response = {
"DeviceReply" : {
"TotalDevices" : 10,
"ReturnCode" : 0,
"RequestId" : "{034DE8DC-F07F-4DCA-0311-12A723B5FB45}",
"StateInfo" : {
"Node" : [ {
"TotalItemsReturned" : 0,
"TotalItemsFound" : 0,
"StateId" : 0,
"SubsystemStartTime" : 1628771536,
"Name" : "10.77.44.104"
}, {
"TotalItemsReturned" : 0,
"TotalItemsFound" : 0,
"StateId" : 0,
"SubsystemStartTime" : 0,
"Name" : "10.77.44.105"
}, {
"TotalItemsReturned" : 10,
"TotalItemsFound" : 10,
"StateId" : 10,
"SubsystemStartTime" : 1628771379,
"Name" : "sapphire-103"
} ]
},
"ReplyNode" : [ {
"ReturnCode" : 1,
"ActiveServices" : 3,
"Name" : "10.77.44.104"
}, {
"ReturnCode" : 1,
"ActiveServices" : 0,
"NoChange" : 1,
"Name" : "10.77.44.105"
}, {
"ReturnCode" : 0,
"ActiveServices" : 3,
"Device" : [ {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "ANN_sapphire-103",
"IpAttribute" : 0,
"Product" : 89,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771393,
"Name" : "ANN_2",
"PerfMonObject" : 682,
"Httpd" : 1,
"Type" : 6,
"Model" : 126,
"IpAddress" : "10.77.44.103",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "ANN_10.77.44.104",
"IpAttribute" : 0,
"Product" : 89,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771535,
"Name" : "ANN_3",
"PerfMonObject" : 682,
"Httpd" : 1,
"Type" : 6,
"Model" : 126,
"IpAddress" : "10.77.44.104",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "CFB_sapphire-103",
"IpAttribute" : 0,
"Product" : 28,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771393,
"Name" : "CFB_2",
"PerfMonObject" : 15,
"Httpd" : 1,
"Type" : 6,
"Model" : 50,
"IpAddress" : "10.77.44.103",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "CFB_10.77.44.104",
"IpAttribute" : 0,
"Product" : 28,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771535,
"Name" : "CFB_3",
"PerfMonObject" : 15,
"Httpd" : 1,
"Type" : 6,
"Model" : 50,
"IpAddress" : "10.77.44.104",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "IVR_sapphire-103",
"IpAttribute" : 0,
"Product" : 36672,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771393,
"Name" : "IVR_2",
"PerfMonObject" : 1462,
"Httpd" : 1,
"Type" : 6,
"Model" : 36219,
"IpAddress" : "10.77.44.103",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "IVR_10.77.44.104",
"IpAttribute" : 0,
"Product" : 36672,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771535,
"Name" : "IVR_3",
"PerfMonObject" : 1462,
"Httpd" : 1,
"Type" : 6,
"Model" : 36219,
"IpAddress" : "10.77.44.104",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "MOH_sapphire-103",
"IpAttribute" : 0,
"Product" : 51,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771393,
"Name" : "MOH_2",
"PerfMonObject" : 6,
"Httpd" : 1,
"Type" : 6,
"Model" : 70,
"IpAddress" : "10.77.44.103",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "MOH_10.77.44.104",
"IpAttribute" : 0,
"Product" : 51,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771535,
"Name" : "MOH_3",
"PerfMonObject" : 6,
"Httpd" : 1,
"Type" : 6,
"Model" : 70,
"IpAddress" : "10.77.44.104",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "MTP_sapphire-103",
"IpAttribute" : 0,
"Product" : 30,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771394,
"Name" : "MTP_2",
"PerfMonObject" : 13,
"Httpd" : 1,
"Type" : 6,
"Model" : 110,
"IpAddress" : "10.77.44.103",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
}, {
"Status" : 1,
"Ipv6Attribute" : 0,
"Description" : "MTP_10.77.44.104",
"IpAttribute" : 0,
"Product" : 30,
"IsCtiControllable" : 0,
"TimeStamp" : 1628771535,
"Name" : "MTP_3",
"PerfMonObject" : 13,
"Httpd" : 1,
"Type" : 6,
"Model" : 110,
"IpAddress" : "10.77.44.104",
"Ipv6Address" : "0000:0000:0000:0000:0000:0000:0000:0000"
} ],
"Name" : "sapphire-103"
} ]
}
}
我尝试在我的spec.ts
文件中编写单元测试,如下所示:
it('should make API call and should show data', () => {
const req = httpTestingController.expectOne('http://localhost:/webrtmt/rest/ast/getDeviceSearch')
const mockResponse = "DeviceReply" : {
"TotalDevices" : 10,
"ReturnCode" : 0,
}
expect(req.request.method).toEqual('POST');
httpClient.post('http://mock-url', {}).subscribe(result => {
expect(result).toEqual(mockResponse);
});
});
我该如何进行?
解决方案
推荐阅读
- sql-server - 对象“服务器”、数据库“主”上的外部访问组件权限被拒绝
- r - 创建一个矩阵 m 并设置为位置 mij = (i+j)*10
- javascript - 使用 javascript 和 html 在 webview 应用程序中打开相机
- karate - 在空手道加特林负载测试中共享连接
- javascript - 从网络摄像头 Ext JS 捕获图片
- dask - 如何在本地集群中动态添加工作人员
- javascript - 我想用 TypeScript 屏蔽反应项目的源代码
- r - 如何在 R 中最接近的 3 个值中进行选择?
- java - SearchView 过滤器按预期工作,但检索片段中 RecyclerView 上的旧项目位置
- r - Rmarkdown 文件中的 DiagrammeR/mermaid 流程图,输出格式为 PDF/LaTex