재스민은 약속을 시험한다.그 후 기능하다
Jasmine에서 앱을 테스트하려고 했는데 다음과 같은 문제가 발생했습니다.
제가 .then
내 약속의 기능.바로 이 시점에서 코드를 테스트해야 합니다.
컨트롤러 코드는 다음과 같습니다.
TestCtrl.$inject = ["$scope", "TestService"];
/* ngInject */
function TestCtrl($scope, TestService) {
$scope.loadData = function () {
TestService.getData().then(function (response) {
$scope.data = response.data;
$scope.filtered = $scope.data.filter(function(item){
if(item.id > 1000){
return true;
}
return false;
})
});
}
}
그리고 내 재스민 테스트 코드:
describe('TestService tests', function () {
var $q;
beforeEach(function () {
module('pilot.fw.user');
});
beforeEach(inject(function (_$q_) {
$q = _$q_;
}));
describe('UserController Tests', function () {
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
this.scope = $rootScope.$new();
this.$rootscope = $rootScope;
this.$httpBackend = _$httpBackend_;
this.scope = $rootScope.$new();
var TestServiceMock = {
getData: function () {
var deferred = $q.defer();
var result = [{
"id": 1720,
"user": 1132
},
{
"id": 720,
"user": 132
}, {
"id": 1721,
"user": 1132
}];
deferred.promise.data = result;
deferred.resolve(result);
return deferred.promise;
}
};
this.controller = $controller('TestCtrl', {
'$scope': this.scope,
'TestService': TestServiceMock
});
}));
it('test', function(){
this.scope.loadData();
expect(true).toBeTruthy();
})
});
});
이상한 점은 (콘솔로그로 테스트)입니다.
- 내 약속은 만들어지고 반환된다.
- loadData 함수가 호출되어 TestService에서 getData() 함수가 호출됩니다.
- 해결된 대로 약속을 반환해도 그 함수의 모든 것이 실행되지 않습니다.
그럼 그 기능 안에서 코드를 테스트하려면 어떻게 해야 하나요?
합니다.
jasmine 'it' 메서드는 비동기 테스트를 호출할 수 있는 완료된 파라미터를 사용합니다.
it('Should be async', function(done) {
someAsyncFunction().then(function(result) {
expect(result).toBe(true);
done();
});
});
원하는 만큼 깊이 들어가세요. 모든 것이 끝나면 반드시 완료하도록 하세요.Jasmine의 기본 타임아웃은 테스트당 5초이므로 비동기 작업이 완료되지 않으면 Jasmine이 크래시됩니다.이 설정은 Configuration에서 변경하거나 단말기에서 설정할 수 있습니다.
이것은 재스민 문서에서 직접 가져온 것으로, 기본 타임아웃 간격을 처리하는 방법을 보여줍니다.
describe("long asynchronous specs", function() {
var originalTimeout;
beforeEach(function() {
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
});
it("takes a long time", function(done) {
setTimeout(function() {
done();
}, 9000);
});
afterEach(function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});
});
10초 안에 안 되면 잘못된 방법이 있을 수 있어요.특히 로컬 서버/db와 통화하는 경우.이 작업은 헤비 계산을 수행 중이거나 그다지 좋지 않은 인터넷 연결을 가진 외부 API에 도달하는 경우에만 이 시간이 걸릴 수 있습니다.모든 것이 로컬일 경우(또는 스터브 또는 조롱!), 5~10초를 초과하는 것은 확실한 빨간색 플래그입니다.
https://codecraft.tv/courses/angular/unit-testing/asynchronous/ 를 봐 주세요.
실제로는 3가지 방법이 있습니다.
1) 일반 IT 사용:
it('test', (done) => {
const spy = spyOn(func, 'bar').and.returnValue(Promise.resolve(true));
spy.calls.mostRecent().returnValue.then(res => {
...your expect here...
done();
})
} );
2) 각각 전에 비동기 사용:
it('test', async(() => {
spyOn(func, 'bar').and.returnValue(Promise.resolve(true));
fixture.whenStable().then(res => {
...your expect here...
})
} ));
3) HTTP 또는 XHR 콜이 없는 경우 fakeAsync를 사용합니다.
it('test', fakeAsync(() => {
spyOn(func, 'bar').and.returnValue(Promise.resolve(true));
tick();
...your expect here...
} ));
이 솔루션이 도움이 되기를 바랍니다.테스트를 할 때 유용한 접근법 중 하나는 의존성을 조롱하는 것입니다.나는 내가 한 일에 대해 가능한 한 언급하려고 노력했다.
var returnMock, $scope, TestServiceMock, controller;
beforeEach(module('app'));
beforeEach(inject(function($controller) {
returnMock = {
then: jasmine.createSpy(),
};
$scope = {};
// first assumption is You are testing TestService extensively,
// I don't care about what getData has to do to get results
// All I care about is it gets called when I call loadData
TestServiceMock = {
getData: jasmine.createSpy().and.returnValue(returnMock);
};
controller = $controller;
}));
it('should load data when loadData function is called and result set is
under 1000', function() {
controller('TestCtrl', {
$scope,
TestServiceMock
});
// another assumption is your data comes back in such a format
// perhaps in the actual code check whether data exists and proceed
// or do some other action
var returnedData = {
data: [
{
id: 1,
name: 'item 1',
},
]
}
// when I execute the function/method
$scope.loadData();
// I expect getData to be called
expect(TestServiceMock.getData).toHaveBeenCalled();
// I expect then to be called and the reason is I mocked it
expect(returnMock.then).toHaveBeenCalledWith(jasmine.any(Function));
returnMock.then.calls.mostRecent().args[0](returnedData);
// expect data on scope to be equal to my mocked data
expect($scope.data).toEqual(returnedData.data);
// don't expect any result because 1 < 1000
expect($scope.filtered).toEqual([]);
expect($scope.filtered.length).toEqual(0);
});
it('should load data when loadData function is called and result set is over 1000',
function() {
controller('TestCtrl', {
$scope,
TestServiceMock
});
var returnedData = {
data: [
{
id: 1,
name: 'item 1',
},
{
id: 1000,
name: 'item 1000',
},
{
id: 1001,
name: 'item 1000',
},
{
id: 1002,
name: 'item 1002',
}
]
}
$scope.loadData();
expect(TestServiceMock.getData).toHaveBeenCalled();
expect(returnMock.then).toHaveBeenCalledWith(jasmine.any(Function));
returnMock.then.calls.mostRecent().args[0](returnedData);
expect($scope.data).toEqual(returnedData.data);
// expect a result because some entries in the mocked data have id > 1000
expect($scope.filtered).toEqual([
{
id: 1001,
name: 'item 1000',
},
{
id: 1002,
name: 'item 1002',
}]);
expect($scope.filtered.length).toEqual(2);
});
공식 Jasmine Docs는 대부분의 개념을 광범위하게 설명한다.솔루션이 도움이 되길 바랍니다!!!!
Angular 1.x 및 2.x+ 프로젝트에서는 어떻게 해야 하는지 알려드리겠습니다.각도 테스트 도구를 사용하여 비동기 테스트에서 콜백/네스트를 제거합니다.angular 1.x에서는 $q와 $rootScope의 조합을 사용합니다.145달러angular 2.x+에서는 fake Async 같은 것을 사용합니다.
it('should simulate promise', inject(function($q, $rootScope) {
var deferred = $q.defer();
var promise = deferred.promise;
var resolvedValue;
promise.then(function(value) { resolvedValue = value; });
expect(resolvedValue).toBeUndefined();
// Simulate resolving of promise
deferred.resolve(123);
// Note that the 'then' function does not get called synchronously.
// This is because we want the promise API to always be async, whether or not
// it got called synchronously or asynchronously.
expect(resolvedValue).toBeUndefined();
// Propagate promise resolution to 'then' functions using $apply().
$rootScope.$apply();
expect(resolvedValue).toEqual(123);
}));
단점은 코드가 angular로 묶여 있다는 것입니다. 장점은 코드가 평평하고 2.x+로 휴대할 수 있다는 것입니다.
저는 모카 테스트 주자의 팬이었습니다. 테스트에서 약속을 돌려줄 수 있었습니다. 하지만 테스트를 위해 코드를 수정해야 한다는 단점도 있습니다.
컨트롤러에 대해서는 이와 같은 값을 반환해야 합니다.
TestCtrl.$inject = ["$scope", "TestService"];
/* ngInject */
function TestCtrl($scope, TestService) {
$scope.loadData = function () {
// Return this call, since it will return a new promise
// This is what let's you do $scope.loadData.then()
return TestService.getData().then(function (response) {
// What you return in here will be the first argument
// of your then method, in the tests / any env
// Ex. return 'foo'
// will result in .then(result => result === 'foo') //=> true
// return one of these, i suggest the data, go SRP!
return $scope.data = response.data;
// I would do this stuff in a separate function, but you
// can return 'filtered' instead if you like.
//
// $scope.filtered = $scope.data.filter(function(item){
// if(item.id > 1000){
// return true;
// }
// return false;
// });
});
}
}
'then' 뒤에 무언가를 부르는 것은 아무런 의미가 없으며, 값은 INSIDE 'then'이라고 불러야 합니다.그 이후나 그 이전이 아니다.하지만 그 안에.톰 그린과 프레디 갓 핑거에 나오는 불쌍한 무스처럼요
언급URL : https://stackoverflow.com/questions/35430827/jasmine-test-a-promise-then-function
'programing' 카테고리의 다른 글
JSON 문자열을 오브젝트로 해석하는 가장 간단한 C# 함수는 무엇입니까? (0) | 2023.04.01 |
---|---|
이 상태랑 이 상태랑 뭐가 달라?setstate를 ReactJS로 설정하시겠습니까? (0) | 2023.04.01 |
JSON 날짜 문자열을 Python 날짜/시간으로 변환 (0) | 2023.04.01 |
create-react-app의 개발 서버가 자동으로 새로 고쳐지지 않음 (0) | 2023.04.01 |
Word press는 사용자가 사이트 내용을 보기 전에 강제로 로그인하도록 합니다. (0) | 2023.04.01 |