Javascript 测试Angularjs 1.6中$q.all()的then中设置的公共值
我试着用 我只想测试公共代码的输入和输出,所以在我的控制器中,“Javascript 测试Angularjs 1.6中$q.all()的then中设置的公共值,javascript,angularjs,unit-testing,Javascript,Angularjs,Unit Testing,我试着用 我只想测试公共代码的输入和输出,所以在我的控制器中,“this.data”属性是最高优先级的。从输入this.data开始很容易,因为它只是测试类构造函数属性,默认设置为undefined 输出是个问题,在获得预期值之前,需要调用大量代码。 问题: 如何附加到$q.all.resolve()并测试this.data的映射输出?期望是expect(ctrl.data).toEqual(expectedData) Controller.js: class Controller { /*
this.data
”属性是最高优先级的。从输入this.data开始很容易,因为它只是测试类构造函数属性,默认设置为undefined
输出是个问题,在获得预期值之前,需要调用大量代码。
问题:
如何附加到$q.all.resolve()并测试this.data
的映射输出?期望是expect(ctrl.data).toEqual(expectedData)
Controller.js:
class Controller {
/**
* @ngInject
*/
constructor(
someService, $q, $scope) {
this.ngScope_ = $scope;
this.someService_ = someService;
this.ngQ_ = $q;
this.data = undefined;
}
$onInit() {
this.getData_();
}
getData_() {
let requests = [1,2];
const REQUEST_TYPE = 'SOME_REQUEST';
const outEachApproval = (d) => d[0].approvals;
const requestsAsArr = requests.split(',');
const promiseArr = requestsAsArr.map(
(i) => this.someService.getAllDataByType(
REQUEST_TYPE, i));
this.ngQ_.all(promiseArr).then((data) => {
this.data = data.map(outEachApproval); // How the hell do I test this.data at this point in time in the unit test?
});
}
Controller_test.js
describe('someModule', ()=> {
let $componentController,
ctrl,
$rootScope,
$q;
const mockData = [[{approvals: [{name: 'hey'}]},{approvals: [{name: 'hey'}]}]];
const expectedData = [[{name:'hey'}],[{name:'hey'}]];
beforeEach(() => {
module(someModule.name);
inject((_$componentController_, _$rootScope_, _$q_) => {
$componentController = _$componentController_;
$q = _$q_;
$rootScope = _$rootScope_;
});
ctrl = $componentController(COMPONENT_NAME,
{
$scope: $rootScope.$new(),
someService: {
getAllDataByType: () => {
return Promise.resolve(mockData);
}
}
}, {});
});
describe('this.data input', ()=> {
it('should be undefined', () => {
expect(ctrl.data).toBeUndefined();
});
});
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
ctrl.$onInit();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
});
我看到了几种处理方法: 弗斯特 首先,让您的
someService
mock在测试中可用:
let someServiceMock = {
getAllDataByType: () => {
//we can leave this empty
}
};
...
beforeEach(() => {
...
ctrl = $componentController(COMPONENT_NAME,
{
$scope: $rootScope.$new(),
someService: someServiceMock
}, {});
});
然后在测试中,只需监视它:
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
//as we use $q.all(), we need to create array of promises
let deferred1 = $q.defer();
...
let deferredN = $q.defer();
let arrayOfPromises = [deferred1.promise, ... ,deferredN.promise];
//then we spy on needed method and mock its return value
spyOn(someServiceMock, 'getAllDataByType').and.returnValue(arrayOfPromises);
ctrl.$onInit();
expect(someServiceMock.getAllDataByType).toHaveBeenCalled();
//now we resolve our promises with any data we want
let resolveData1 = /*Promise#1 mocked data*/;
deferred1.resolve(resolveData1)
let resolveData2 = /*Promise#2 mocked data*/;
deferred2.resolve(resolveData2)
...
let resolveDataN = /*Promise#N mocked data*/;
deferredN.resolve(resolveDataN)
//$q.all() returns array, so expectedData would be array
let expectedData = [
resolveData1,
resolveData2,
...
resolveDataN
];
//then we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
let deferred = $q.defer();
spyOn($qMock, 'all').and.returnValue(deferred.promise);
ctrl.$onInit();
expect($qMock.all).toHaveBeenCalled();
deferred.resolve(expectedData);
//now we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
是一个简单的plunker,可与多个$q.defer()
实例一起使用
顺便说一句,如果someServiceMock.getAllDataByType()
中的请求是通过angular实现的,那么您可以使用服务来模拟它们
第二 在组件控制器中为
$q
服务创建模拟:
let $qMock = {
all: () => {
//we can leave this empty
}
}
...
beforeEach(() => {
...
ctrl = $componentController(COMPONENT_NAME,
{
$scope: $rootScope.$new(),
someService: {
getAllDataByType: () => {
return Promise.resolve(mockData);
}
},
$q: $qMock
}, {});
});
然后在测试中,只需监视它:
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
//as we use $q.all(), we need to create array of promises
let deferred1 = $q.defer();
...
let deferredN = $q.defer();
let arrayOfPromises = [deferred1.promise, ... ,deferredN.promise];
//then we spy on needed method and mock its return value
spyOn(someServiceMock, 'getAllDataByType').and.returnValue(arrayOfPromises);
ctrl.$onInit();
expect(someServiceMock.getAllDataByType).toHaveBeenCalled();
//now we resolve our promises with any data we want
let resolveData1 = /*Promise#1 mocked data*/;
deferred1.resolve(resolveData1)
let resolveData2 = /*Promise#2 mocked data*/;
deferred2.resolve(resolveData2)
...
let resolveDataN = /*Promise#N mocked data*/;
deferredN.resolve(resolveDataN)
//$q.all() returns array, so expectedData would be array
let expectedData = [
resolveData1,
resolveData2,
...
resolveDataN
];
//then we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
let deferred = $q.defer();
spyOn($qMock, 'all').and.returnValue(deferred.promise);
ctrl.$onInit();
expect($qMock.all).toHaveBeenCalled();
deferred.resolve(expectedData);
//now we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
这个测试比较简单,但请注意,它并不取决于someService.getAllDataByType()
将返回什么
一些关于该主题的有用文章:
- $q
someService
mock在测试中可用:
let someServiceMock = {
getAllDataByType: () => {
//we can leave this empty
}
};
...
beforeEach(() => {
...
ctrl = $componentController(COMPONENT_NAME,
{
$scope: $rootScope.$new(),
someService: someServiceMock
}, {});
});
然后在测试中,只需监视它:
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
//as we use $q.all(), we need to create array of promises
let deferred1 = $q.defer();
...
let deferredN = $q.defer();
let arrayOfPromises = [deferred1.promise, ... ,deferredN.promise];
//then we spy on needed method and mock its return value
spyOn(someServiceMock, 'getAllDataByType').and.returnValue(arrayOfPromises);
ctrl.$onInit();
expect(someServiceMock.getAllDataByType).toHaveBeenCalled();
//now we resolve our promises with any data we want
let resolveData1 = /*Promise#1 mocked data*/;
deferred1.resolve(resolveData1)
let resolveData2 = /*Promise#2 mocked data*/;
deferred2.resolve(resolveData2)
...
let resolveDataN = /*Promise#N mocked data*/;
deferredN.resolve(resolveDataN)
//$q.all() returns array, so expectedData would be array
let expectedData = [
resolveData1,
resolveData2,
...
resolveDataN
];
//then we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
let deferred = $q.defer();
spyOn($qMock, 'all').and.returnValue(deferred.promise);
ctrl.$onInit();
expect($qMock.all).toHaveBeenCalled();
deferred.resolve(expectedData);
//now we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
是一个简单的plunker,可与多个$q.defer()
实例一起使用
顺便说一句,如果someServiceMock.getAllDataByType()
中的请求是通过angular实现的,那么您可以使用服务来模拟它们
第二 在组件控制器中为
$q
服务创建模拟:
let $qMock = {
all: () => {
//we can leave this empty
}
}
...
beforeEach(() => {
...
ctrl = $componentController(COMPONENT_NAME,
{
$scope: $rootScope.$new(),
someService: {
getAllDataByType: () => {
return Promise.resolve(mockData);
}
},
$q: $qMock
}, {});
});
然后在测试中,只需监视它:
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
//as we use $q.all(), we need to create array of promises
let deferred1 = $q.defer();
...
let deferredN = $q.defer();
let arrayOfPromises = [deferred1.promise, ... ,deferredN.promise];
//then we spy on needed method and mock its return value
spyOn(someServiceMock, 'getAllDataByType').and.returnValue(arrayOfPromises);
ctrl.$onInit();
expect(someServiceMock.getAllDataByType).toHaveBeenCalled();
//now we resolve our promises with any data we want
let resolveData1 = /*Promise#1 mocked data*/;
deferred1.resolve(resolveData1)
let resolveData2 = /*Promise#2 mocked data*/;
deferred2.resolve(resolveData2)
...
let resolveDataN = /*Promise#N mocked data*/;
deferredN.resolve(resolveDataN)
//$q.all() returns array, so expectedData would be array
let expectedData = [
resolveData1,
resolveData2,
...
resolveDataN
];
//then we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
describe('this.data output', ()=> {
it('should be equal to expectedData after init', (done) => {
let deferred = $q.defer();
spyOn($qMock, 'all').and.returnValue(deferred.promise);
ctrl.$onInit();
expect($qMock.all).toHaveBeenCalled();
deferred.resolve(expectedData);
//now we need to apply changes
$rootScope.$apply();
expect(ctrl.data).toEqual(expectedData);
ctrl.ngScope_.$apply();
done();
});
});
这个测试比较简单,但请注意,它并不取决于someService.getAllDataByType()
将返回什么
一些关于该主题的有用文章:
- $q
outEachApproval
功能传递解析数据。因此,在我的回答中,expectedData
应替换为expectedData=expectedData.map(outEachApproval)
。但您最好将initoutEachApproval
作为控制器方法,以便能够在测试中使用它。例如,let outEachApproval=ctrl.\u outEachApproval
(在测试中)。对不起,我没有注意到您通过本地outEachApproval
函数传递解析数据。因此,在我的回答中,expectedData
应替换为expectedData=expectedData.map(outEachApproval)
。但您最好将initoutEachApproval
作为控制器方法,以便能够在测试中使用它。例如,让outEachApproval=ctrl.\u outEachApproval
(在测试中)。