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)
。但您最好将init
outEachApproval
作为控制器方法,以便能够在测试中使用它。例如,
let outEachApproval=ctrl.\u outEachApproval
(在测试中)。对不起,我没有注意到您通过本地
outEachApproval
函数传递解析数据。因此,在我的回答中,
expectedData
应替换为
expectedData=expectedData.map(outEachApproval)
。但您最好将init
outEachApproval
作为控制器方法,以便能够在测试中使用它。例如,
让outEachApproval=ctrl.\u outEachApproval
(在测试中)。