gpt4 book ai didi

angularjs - chai-as-promised 错误地通过了测试

转载 作者:行者123 更新时间:2023-12-04 17:34:43 25 4
gpt4 key购买 nike

我正在尝试为返回 Angular promise ($q 库)的方法编写测试。

我不知所措。我正在使用 Karma 运行测试,我需要弄清楚如何确认 AccountSearchResult.validate()函数返回一个promise,确认promise是否被拒绝,并检查promise返回的对象。

例如,正在测试的方法具有以下(简化):

.factory('AccountSearchResult', ['$q',
function($q) {

return {
validate: function(result) {
if (!result.accountFound) {
return $q.reject({
message: "That account or userID was not found"
});
}
else {
return $q.when(result);
}
}
};
}]);

我想我可以写一个这样的测试:
    it("it should return an object with a message property", function () {
promise = AccountSearchResult.validate({accountFound:false});
expect(promise).to.eventually.have.property("message"); // PASSES
});

这通过了,但这样做(错误地):
    it("it should return an object with a message property", function () {
promise = AccountSearchResult.validate({accountFound:false});
expect(promise).to.eventually.have.property("I_DONT_EXIST"); // PASSES, should fail
});

我正在尝试“最终”使用 chai-as-promised,但我所有的测试都通过了误报:
    it("it should return an object", function () {
promise = AccountSearchResult.validate();
expect(promise).to.eventually.be.an('astronaut');
});

将通过。在查看文档和 SO 问题时,我看到了以下示例:
expect(promise).to.eventually.to.equal('something');
return promise.should.eventually.equal('something');
expect(promise).to.eventually.to.equal('something', "some message about expectation.");
expect(promise).to.eventually.to.equal('something').notify(done);
return assert.becomes(promise, "something", "message about assertion");
wrapping expectation in runs() block
wrapping expectation in setTimeout()

使用 .should给我 Cannot read property 'eventually' of undefined .我错过了什么?

最佳答案

事实证明,@runTarm 的建议都是正确的。我认为问题的根源在于 angular's $q library与 angular 的 $digest 循环有关。因此,虽然调用 $apply 有效,但我相信它有效的原因是因为 $apply 最终还是调用了 $digest。通常我认为 $apply() 是一种让 Angular 了解其世界之外发生的事情的方法,但我没有想到在测试的上下文中,解决 $q promise 的 .then()/.catch()在运行期望之前可能需要插入,因为 $q 直接被烘焙成 Angular 。唉。

我能够让它以 3 种不同的方式工作,一种是 runs() block (和 $digest/$apply),以及 2 个没有 runs() block (和 $digest/$apply)。

提供一个完整的测试可能是矫枉过正,但在寻找答案时,我发现自己希望人们发布他们如何注入(inject)/ stub /设置服务,以及不同的 expect语法,所以我将发布我的整个测试。

describe("AppAccountSearchService", function () {
var expect = chai.expect;

var $q,
authorization,
AccountSearchResult,
result,
promise,
authObj,
reasonObj,
$rootScope,
message;

beforeEach(module(
'authorization.services', // a dependency service I need to stub out
'app.account.search.services' // the service module I'm testing
));

beforeEach(inject(function (_$q_, _$rootScope_) {
$q = _$q_; // native angular service
$rootScope = _$rootScope_; // native angular service
}));

beforeEach(inject(function ($injector) {
// found in authorization.services
authObj = $injector.get('authObj');
authorization = $injector.get('authorization');

// found in app.account.search.services
AccountSearchResult = $injector.get('AccountSearchResult');
}));

// authObj set up
beforeEach(inject(function($injector) {
authObj.empAccess = false; // mocking out a specific value on this object
}));

// set up spies/stubs
beforeEach(function () {
sinon.stub(authorization, "isEmployeeAccount").returns(true);
});

describe("AccountSearchResult", function () {

describe("validate", function () {

describe("when the service says the account was not found", function() {

beforeEach(function () {
result = {
accountFound: false,
accountId: null
};

AccountSearchResult.validate(result)
.then(function() {
message = "PROMISE RESOLVED";
})
.catch(function(arg) {
message = "PROMISE REJECTED";
reasonObj = arg;
});
// USING APPLY... this was the 'magic' I needed
$rootScope.$apply();
});

it("should return an object", function () {
expect(reasonObj).to.be.an.object;
});

it("should have entered the 'catch' function", function () {
expect(message).to.equal("PROMISE REJECTED");
});

it("should return an object with a message property", function () {
expect(reasonObj).to.have.property("message");
});
// other tests...
});


describe("when the account ID was falsey", function() {
// example of using runs() blocks.
//Note that the first runs() content could be done in a beforeEach(), like above
it("should not have entered the 'then' function", function () {
// executes everything in this block first.
// $rootScope.apply() pushes promise resolution to the .then/.catch functions
runs(function() {
result = {
accountFound: true,
accountId: null
};

AccountSearchResult.validate(result)
.then(function() {
message = "PROMISE RESOLVED";
})
.catch(function(arg) {
reasonObj = arg;
message = "PROMISE REJECTED";
});

$rootScope.$apply();
});

// now that reasonObj has been populated in prior runs() bock, we can test it in this runs() block.
runs(function() {
expect(reasonObj).to.not.equal("PROMISE RESOLVED");
});

});
// more tests.....
});

describe("when the account is an employee account", function() {
describe("and the user does not have EmployeeAccess", function() {

beforeEach(function () {
result = {
accountFound: true,
accountId: "160515151"
};

AccountSearchResult.validate(result)
.then(function() {
message = "PROMISE RESOLVED";
})
.catch(function(arg) {
message = "PROMISE REJECTED";
reasonObj = arg;
});
// digest also works
$rootScope.$digest();
});

it("should return an object", function () {
expect(reasonObj).to.be.an.object;
});

// more tests ...
});
});
});
});
});

现在我知道了修复方法,阅读 $q docs 就很明显了。在测试部分下,它特别说要调用 $rootScope.apply()。由于我能够让它同时使用 $apply() 和 $digest(),我怀疑 $digest 确实是需要调用的,但根据文档,$apply() 可能是“最佳实践” .

$apply vs $digest上的体面故障.

最后,留给我的唯一谜团是为什么测试默认通过了。我知道我达到了预期(他们正在运行)。那么为什么 expect(promise).to.eventually.be.an('astronaut');成功?/耸耸肩

希望有帮助。感谢您朝着正确的方向插入。

关于angularjs - chai-as-promised 错误地通过了测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25369692/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com