source

Jasmine 2.0을 사용한 비동기 테스트에서 "$digest aready progress"가 표시됨

myloves 2023. 3. 4. 15:28

Jasmine 2.0을 사용한 비동기 테스트에서 "$digest aready progress"가 표시됨

나는 그 소명을 안다.$digest또는$apply다이제스트 사이클 중에 수동으로 "$digest already in progress" 오류가 발생하지만 왜 여기서 이 오류가 발생하는지 알 수 없습니다.

이것은 서비스 유닛테스트입니다.$http서비스는 충분히 심플합니다.콜을 실행하려고 하는 코드가 예기한 데이터를 계속 얻을 수 있도록 하면서 서버에 대한 중복 콜을 회피할 뿐입니다.

angular.module('services')
    .factory('httpService', ['$http', function($http) {

        var pendingCalls = {};

        var createKey = function(url, data, method) {
            return method + url + JSON.stringify(data);
        };

        var send = function(url, data, method) {
            var key = createKey(url, data, method);
            if (pendingCalls[key]) {
                return pendingCalls[key];
            }
            var promise = $http({
                method: method,
                url: url,
                data: data
            });
            pendingCalls[key] = promise;
            promise.then(function() {
                delete pendingCalls[key];
            });
            return promise;
        };

        return {
            post: function(url, data) {
                return send(url, data, 'POST');
            },
            get: function(url, data) {
                return send(url, data, 'GET');
            },
            _delete: function(url, data) {
                return send(url, data, 'DELETE');
            }
        };
    }]);

유닛 테스트도 매우 간단합니다.$httpBackend요구를 상정합니다.

it('does GET requests', function(done) {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    service.get('/some/random/url').then(function(result) {
        expect(result.data).toEqual('The response');
        done();
    });
    $httpBackend.flush();
});

이것은 와 같이 폭발한다.done()"$syslog aready in progress" 오류와 함께 호출됩니다.왜 그랬는지 모르겠어.나는 이것을 포장해서 해결할 수 있다.done()이런 타임아웃에

setTimeout(function() { done() }, 1);

즉,done()$digest가 완료된 후 큐잉되어 실행되지만 문제가 해결되는 동안 알고 싶습니다.

  • 애초에 Angular가 다이제스트 사이클에 있는 이유는 무엇입니까?
  • 콜은 왜?done()이 오류를 트리거하시겠습니까?

Jasmine 1.3에서도 동일한 테스트를 Green으로 실행했는데, 이는 Jasmine 2.0으로 업그레이드하고 새로운 비동기 구문 분석을 사용하기 위해 테스트를 다시 작성한 후에만 발생합니다.

$httpBacked.flush()를 실제로 기동하여 완료$digest()어제 하루종일 ngResource와 angular-mocks의 출처를 조사했는데도 아직 완전히 이해하지 못했습니다.

내가 알기로는 의 목적은$httpBackend.flush()위의 비동기 구조를 완전히 회피하는 것입니다.즉, 의 구문은it('should do something',function(done){});그리고.$httpBackend.flush()사이가 좋지 않다바로 그 목적.flush()보류 중인 비동기 콜백을 푸시하고 되돌리는 것입니다.마치 큰 것 같다done모든 비동기 콜백을 랩핑합니다.

따라서 올바르게 이해하고 있는 경우(그리고 현재 기능하고 있는 경우) 올바른 방법은 이 명령어를 삭제하는 것입니다.done()프로세서(사용 시)$httpBackend.flush():

it('does GET requests', function() {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    service.get('/some/random/url').then(function(result) {
        expect(result.data).toEqual('The response');
    });
    $httpBackend.flush();
});

console.log 문을 추가하면 모든 콜백이 다음 중 일관되게 발생합니다.flush()사이클:

it('does GET requests', function() {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    console.log("pre-get");
    service.get('/some/random/url').then(function(result) {
        console.log("async callback begin");
        expect(result.data).toEqual('The response');
        console.log("async callback end");
    });
    console.log("pre-flush");
    $httpBackend.flush();
    console.log("post-flush");
});

다음으로 출력은 다음과 같습니다.

프리겟

사전 준비

비동기 콜백 시작

비동기 콜백엔드

사후 처리

매번.정말 보고 싶다면 스코프를 잡고scope.$$phase

var scope;
beforeEach(function(){
    inject(function($rootScope){
        scope = $rootScope;
    });
});
it('does GET requests', function() {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    console.log("pre-get "+scope.$$phase);
    service.get('/some/random/url').then(function(result) {
        console.log("async callback begin "+scope.$$phase);
        expect(result.data).toEqual('The response');
        console.log("async callback end "+scope.$$phase);
    });
    console.log("pre-flush "+scope.$$phase);
    $httpBackend.flush();
    console.log("post-flush "+scope.$$phase);
});

출력은 다음과 같습니다.

사전 정의되지 않음

사전 정의가 정의되지 않음

비동기 콜백 시작 $syslog

비동기 콜백 종료 $syslog

정의되어 있지 않다

@ 그 @deitch가 맞다.$httpBacked.flush()다이제스트를 트리거합니다.는 이 입니다.$httpBackend.verifyNoOutstandingExpectation(); 뒤에 .it완성되면 다이제스트도 있습니다.하다

  1. 은 ""라고 부른다"flush().
  2. then()
  3. done()
  4. verifyNoOutstandingExpectation()다이제스트를 트리거하는 실행입니다만, 이미 다이제스트에 들어가 있기 때문에 에러가 발생합니다.

done()까지는 '아'가한데, ''아'가 있어야 입니다.then()실행까지 됩니다. 경우,then실행되지 않으면 장애가 발생했음을 알 수 있습니다.가 잘 입니다.done().

it('does GET requests', function(done) {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    service.get('/some/random/url').then(function(result) {
        expect(result.data).toEqual('The response');
        setTimeout(done, 0); // run the done() after the current $digest is complete.
    });
    $httpBackend.flush();
});

「 」를 .done()타임아웃 시 현재 다이제스트가 완료된 후 즉시 실행됩니다., 「」의 됩니다.expects도망가고 싶었던 게 실제로 도망가는 거야

@deitch의 답변에 추가.테스트를 보다 견고하게 하기 위해 콜백 전에 스파이를 추가할 수 있습니다.이것에 의해, 콜백이 실제로 콜 되는 것이 보증됩니다.

it('does GET requests', function() {
  var callback = jasmine.createSpy().and.callFake(function(result) {
    expect(result.data).toEqual('The response');
  });

  $httpBackend.expectGET('/some/random/url').respond('The response');
  service.get('/some/random/url').then(callback);
  $httpBackend.flush();

  expect(callback).toHaveBeenCalled();
});

언급URL : https://stackoverflow.com/questions/24341544/getting-digest-already-in-progress-in-async-test-with-jasmine-2-0