2017-08-01 97 views
3

我們在用Jasmine測試異步代碼時遇到意想不到的行爲。據我們所知,當您使用done函數時,直到完成執行纔會調用期望。但是,這不會發生,因爲第二個期望失敗,因此$ctrl.todos分配從來沒有發生過用茉莉花測試異步函數

不工作測試

it('initializes the data when $onIinit', (done) => { 
    const expected = 'some result'; 
    const response = Promise.resolve(expected); 

    spyOn(myService, 'getAll').and.returnValue(response); 

    // This method calls myService.getAll 
    $ctrl.$onInit(); 

    expect(myService.getAll).toHaveBeenCalled(); 
    expect($ctrl.todos).toEqual(false); 

    response.then(done); 
}); 

輸出:預期不確定等於假

。另一方面,這是工作:

it('initializes the data when $onIinit', (done) => { 
    const expected = 'some result'; 
    const response = Promise.resolve(expected); 

    spyOn(myService, 'getAll').and.returnValue(response); 

    // This method calls myService.getAll 
    $ctrl.$onInit(); 

    expect(myService.getAll).toHaveBeenCalled(); 
    response 
     .then(() => expect($ctrl.todos).toBe(expected)) 
     .then(done); 
    }); 

輸出:檢驗合格

控制器的方法:

$ctrl.$onInit =() => { 
    myService.getAll().then((data) => { 
    $ctrl.todos = data; 
    }); 
}; 

回答

1

我找到了一個解決方案。我真的不需要另一個then。在調用完成之前,done的規範將不會完成。此外,它應該始終放在預期之後。

工作代碼:

it('initializes the data when $onIinit', (done) => { 
    const expected = 'some result'; 
    const response = Promise.resolve(expected); 
    spyOn(myService, 'getAll').and.returnValue(response); 
    $ctrl.$onInit(); 

    expect(myService.getAll).toHaveBeenCalled(); 
    response 
    .then(() => { 
     expect($ctrl.todos).toBe(expected); 
     done(); 
    }); 
}); 
0

你的形式給出了似乎是正確的,而且很可能調用內afterEachdone會使它的工作原理。

afterEach(function(done) { 
    done(); 
}, 1000); 

不過,我會建議使用$httpBackend,適用於使用$http service單元測試應用程序的假HTTP後端實現。反正我們用angularjs吧?那麼,爲什麼不利用?

隨着$httpBackend我們可以做出請求,然後與模擬數據進行響應,而無需真正將請求發送到真實服務器。這裏的ilustrative例如

it('initializes the data when $onIinit',() => { 
    const mockData = { data: { expected: 'some result' } }; 

    spyOn(myService, 'getAll').and.callThrough(); 

    $httpBackend.expect('POST', '/my-service/url').respond(200, mockData); 

    // This method calls myService.getAll 
    $ctrl.$onInit(); 

    //flush pending request 
    $httpBackend.flush(); 

    expect(myService.getAll).toHaveBeenCalled(); 
    expect($ctrl.todos).toBeDefined(); 
}); 

幾點說明,$httpBackend.expect('POST', '/my-service/url'),在這裏指出,'POST'需要匹配myService.getAll使用您的服務method,並'/my-service/url'urlmyService.getAll也使用你的服務。

需要撥打$httpBackend.flush();,它會釋放所有未決的請求。

您將需要注入$httpBackend到你的測試,一個簡單的方法是

describe('$httpBackend service in module ngMock',() => { 
    let $httpBackend; 

    beforeEach(inject(['$httpBackend', (_$httpBackend) => { 
     $httpBackend = _$httpBackend; 
    }])); 

    it('$httpBackend is defined',() => { 
     // here we can use $httpBackend 
     expect($httpBackend).toBeDefined(); 
    }); 
}); 

另外,還要注意$httpBackendngMock模塊的一部分。

有關測試angularjs代碼here

希望它可以幫助

-1

Promise是從外部角度世界更多信息 - 你必須等待結果,將在接下來的事件隊列蜱可用 - 髒(幾乎髒)黑客就是用setTimeout

angular.module('test', []) 
 
    .controller('underTest', function($scope, myService) { 
 
    $scope.$onInit = function() { 
 
     myService.getAll().then(function(data) { 
 
     $scope.todos = data 
 
     }) 
 
    } 
 
    }) 
 

 
describe('Controller: somethingChanged', function() { 
 
    var scope, myService 
 

 
    beforeEach(function() { 
 
    module('test') 
 
    }) 
 

 
    beforeEach(function() { 
 
    module(function($provide) { 
 
     $provide.value('myService', { 
 
     getAll: function() {} 
 
     }) 
 
    }) 
 
    }) 
 

 
    beforeEach(inject(function($controller, _$rootScope_, _myService_) { 
 
    myService = _myService_ 
 
    scope = _$rootScope_.$new() 
 
    $controller('underTest', { 
 
     $scope: scope 
 
    }) 
 
    })) 
 

 
    it('initializes the data when $onIinit', function(done) { 
 
    const expected = 'some result' 
 
    const response = Promise.resolve(expected) 
 

 
    spyOn(myService, 'getAll').and.returnValue(response) 
 

 
    scope.$onInit() 
 

 
    expect(myService.getAll).toHaveBeenCalled(); 
 

 
    setTimeout(function() { 
 
     expect(scope.todos).toEqual(expected) 
 
     done() 
 
    }) 
 
    }); 
 
});
<script src="https://cdn.jsdelivr.net/jasmine/2.6.1/jasmine.js"></script> 
 
<script src="https://cdn.jsdelivr.net/jasmine/2.6.1/jasmine-html.js"></script> 
 
<script src="https://cdn.jsdelivr.net/jasmine/2.6.1/boot.js"></script> 
 
<link rel="stylesheet" href="https://cdn.jsdelivr.net/jasmine/2.6.1/jasmine.css" /> 
 

 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-mocks.js"></script>