Angularjs 与茉莉花一起使用上下文
我想和jasmine一起使用上下文,这样我就可以组织我的模拟返回的内容。下面是一些伪代码来演示我要做的事情。我希望这两个期望都能实现:Angularjs 与茉莉花一起使用上下文,angularjs,jasmine,angular-mock,Angularjs,Jasmine,Angular Mock,我想和jasmine一起使用上下文,这样我就可以组织我的模拟返回的内容。下面是一些伪代码来演示我要做的事情。我希望这两个期望都能实现: describe('a module', function(){ var whatTheFunctionReturns; beforeEach(function(){ module('anApp', function($provide){ $provide.value('aFactory', { aFunc
describe('a module', function(){
var whatTheFunctionReturns;
beforeEach(function(){
module('anApp', function($provide){
$provide.value('aFactory', { aFunction: whatTheFunctionReturns })
}
});
describe('when the function returns alpha', function(){
whatTheFunctionReturns = 'alpha'
it('should get data from a service', function(){
expect(aFactory.aFunction).toEqual( 'alpha' )
});
});
describe('when the function returns beta', function(){
whatTheFunctionReturns = 'beta'
it('should get data from a service', function(){
expect(aFactory.aFunction).toEqual( 'beta' )
});
});
});
请仔细阅读以上内容。你明白我想做什么吗?代码
$provide.value('aFactory', { aFunction: whatTheFunctionReturns })
在beforeach块中写入一次,但变量
whatTheFunctionReturns
在两个描述块中更改,当函数返回alpha时
和当函数返回beta时
但是,它不起作用。下面是一些真实的代码,我试图测试一个控制器并模拟它所依赖的工厂:
describe('firstController', function(){
var $rootScope, $scope, $controller
var message = 'I am message default'
beforeEach(function(){
module('App',function($provide){
$provide.value('ServiceData', { message: message})
});
inject(function(_$rootScope_,_$controller_){
$rootScope = _$rootScope_
$scope = $rootScope.$new()
$controller = _$controller_
$controller('firstController', { '$rootScope' : $rootScope, '$scope' : $scope })
});
});
describe('when message 1', function(){
beforeEach(function(){
message = 'I am message one'
});
it('should get data from a service', function(){
expect($scope.serviceData.message).toEqual( '1' ) // using wrong data so I can see what data is being returned in the error message
});
});
describe('when message 2', function(){
beforeEach(function(){
message = 'I am message two'
});
it('should get data from a service', function(){
expect($scope.serviceData.message).toEqual( '2' ) // using wrong data so I can see what data is being returned in the error message
});
});
});
以下是我收到的错误消息:
Firefox 34.0.0 (Ubuntu) firstController when message 1 should get data from a service FAILED
Expected 'I am message default' to equal '1'.
Firefox 34.0.0 (Ubuntu) firstController when message 2 should get data from a service FAILED
Expected 'I am message one' to equal '2'.
它工作了一半。变量正在更新,但仅在最后一个描述块中('when message 2'
)以下是我希望返回的内容:
Firefox 34.0.0 (Ubuntu) firstController when message 1 should get data from a service FAILED
Expected 'I am message one' to equal '1'.
Firefox 34.0.0 (Ubuntu) firstController when message 2 should get data from a service FAILED
Expected 'I am message two' to equal '2'.
我怎样才能做到这一点?你明白我想用descripe块做什么吗?你误解了Jasmine在执行每个测试之前是如何构建测试用例的
看看这个,然后执行它:
describe("Test", function(){
console.info("Calling beforeEach() before describe()");
beforeEach(function(){
console.info("Running before()");
});
console.info("Calling describe() A");
describe("describe A", function(){
console.info("Calling it() A 0");
it('should A 0', function(){
console.info("Running it() A 1");
expect("test to be").toBe("implemented");
});
console.info("Calling it() A 1");
it('should A 1', function(){
console.info("Running it() A 2");
expect("test to be").toBe("implemented");
});
console.info("Calling it() A 2");
it('should A 2', function(){
console.info("Running it() A 3");
expect("test to be").toBe("implemented");
});
});
});
在控制台中,您将观察到以下情况:
Calling beforeEach() before describe()
Calling describe() A
Calling it() A 0
Calling it() A 1
Calling it() A 2
Running before()
Running it() A 1
Running before()
Running it() A 2
Running before()
Running it() A 3
这是怎么回事
调用descripe()
时,将执行您提供的回调函数中的代码。对其他descripe()
s的后续调用将执行对的回调。对it()
、beforeach()
和afterEach()
的每次调用都将在内部队列树中对传递的回调进行排队,before将前置到每个分支,after将追加到该分支。然后队列一个接一个地移动,Jasmine将为每个步骤执行存储的回调
当查看第一个代码时,这意味着执行函数返回的所有赋值,然后执行每个it()
(前面是beforeach()
)
你应该做什么:
describe('a module', function(){
var whatTheFunctionReturns;
// pepare to run in beforeEach()
function _beforeModule(){
module('anApp', function($provide){
$provide.value('aFactory', { aFunction: whatTheFunctionReturns })
}
}
describe('when the function returns alpha', function(){
beforeEach(function(){
whatTheFunctionReturns = 'alpha';
_beforeModule();
});
it('should get data from a service', function(){
expect(aFactory.aFunction).toEqual( 'alpha' )
});
});
describe('when the function returns beta', function(){
beforeEach(function(){
whatTheFunctionReturns = 'beta';
_beforeModule();
});
it('should get data from a service', function(){
expect(aFactory.aFunction).toEqual( 'beta' )
});
});
});
您必须将分配包装到beforeach()
或it()
块中。您误解了Jasmine在执行每个测试之前是如何构建测试用例的
看看这个,然后执行它:
describe("Test", function(){
console.info("Calling beforeEach() before describe()");
beforeEach(function(){
console.info("Running before()");
});
console.info("Calling describe() A");
describe("describe A", function(){
console.info("Calling it() A 0");
it('should A 0', function(){
console.info("Running it() A 1");
expect("test to be").toBe("implemented");
});
console.info("Calling it() A 1");
it('should A 1', function(){
console.info("Running it() A 2");
expect("test to be").toBe("implemented");
});
console.info("Calling it() A 2");
it('should A 2', function(){
console.info("Running it() A 3");
expect("test to be").toBe("implemented");
});
});
});
在控制台中,您将观察到以下情况:
Calling beforeEach() before describe()
Calling describe() A
Calling it() A 0
Calling it() A 1
Calling it() A 2
Running before()
Running it() A 1
Running before()
Running it() A 2
Running before()
Running it() A 3
这是怎么回事
调用descripe()
时,将执行您提供的回调函数中的代码。对其他descripe()
s的后续调用将执行对的回调。对it()
、beforeach()
和afterEach()
的每次调用都将在内部队列树中对传递的回调进行排队,before将前置到每个分支,after将追加到该分支。然后队列一个接一个地移动,Jasmine将为每个步骤执行存储的回调
当查看第一个代码时,这意味着执行函数返回的所有赋值,然后执行每个it()
(前面是beforeach()
)
你应该做什么:
describe('a module', function(){
var whatTheFunctionReturns;
// pepare to run in beforeEach()
function _beforeModule(){
module('anApp', function($provide){
$provide.value('aFactory', { aFunction: whatTheFunctionReturns })
}
}
describe('when the function returns alpha', function(){
beforeEach(function(){
whatTheFunctionReturns = 'alpha';
_beforeModule();
});
it('should get data from a service', function(){
expect(aFactory.aFunction).toEqual( 'alpha' )
});
});
describe('when the function returns beta', function(){
beforeEach(function(){
whatTheFunctionReturns = 'beta';
_beforeModule();
});
it('should get data from a service', function(){
expect(aFactory.aFunction).toEqual( 'beta' )
});
});
});
您必须将工作分配包装到beforeach()
或it()
块中。不幸的是,Jasmine在its中没有概念,这意味着在技术上不可能使用动态范围重用您的期望主体,并根据不同的值测试其行为。为了使Jasmine具有这种级别的可重用性,您所做的一切都是一种变通方法,而不是由创建者设计的
在您的演示代码中,当您在第一个beforeach中调用$controller函数时,无论您做什么,它都将使用默认值解析其所有依赖项
$controller('firstController', { '$rootScope' : $rootScope, '$scope' : $scope })
不幸的是,Jasmine在其中没有概念,这意味着在技术上不可能重用具有动态范围的期望主体,并根据不同的值测试其行为。为了使Jasmine具有这种级别的可重用性,您所做的一切都是一种变通方法,而不是由创建者设计的
在您的演示代码中,当您在第一个beforeach中调用$controller函数时,无论您做什么,它都将使用默认值解析其所有依赖项
$controller('firstController', { '$rootScope' : $rootScope, '$scope' : $scope })
我相信您遇到的问题是,用于在服务中分配“消息”的变量只是一个值对象。这是一个javascript问题,而不是jasmine问题
在将其分配给提供给服务的对象之后,修改它并不重要。例如:
var a = 1;
var b = a;
a = 2;
console.log(b); // will print out '1'
您想要的是能够在每次首次访问之后修改您提供给服务的对象,如下所示:
describe('firstController', function() {
var $rootScope, $scope, $controller, serviceData
beforeEach(function(){
serviceData = { message: 'I am message default' }
module('App',function($provide){
$provide.value('ServiceData', serviceData) // keep a reference to the object
});
inject(function(_$rootScope_,_$controller_){
$rootScope = _$rootScope_
$scope = $rootScope.$new()
$controller = _$controller_
$controller('firstController', { '$rootScope' : $rootScope, '$scope' : $scope })
});
});
describe('when message 1', function(){
beforeEach(function(){
serviceData.message = 'I am message one' // that way, you modify the object that your 'ServiceData' provider holds.
});
it('should get data from a service', function(){
expect($scope.serviceData.message).toEqual( '1' )
});
});
describe('when message 2', function(){
beforeEach(function(){
serviceData.message = 'I am message two'
});
it('should get data from a service', function(){
expect($scope.serviceData.message).toEqual( '2' )
});
});
});
免责声明:我不能100%确定$PROFECT.value的内部工作原理。如果上述方法不起作用,可能是因为$provide.value函数的对象是在内部克隆的。我相信您遇到的问题是,用于在服务中分配“消息”的变量只是一个值对象。这是一个javascript问题,而不是jasmine问题
在将其分配给提供给服务的对象之后,修改它并不重要。例如:
var a = 1;
var b = a;
a = 2;
console.log(b); // will print out '1'
您想要的是能够在每次首次访问之后修改您提供给服务的对象,如下所示:
describe('firstController', function() {
var $rootScope, $scope, $controller, serviceData
beforeEach(function(){
serviceData = { message: 'I am message default' }
module('App',function($provide){
$provide.value('ServiceData', serviceData) // keep a reference to the object
});
inject(function(_$rootScope_,_$controller_){
$rootScope = _$rootScope_
$scope = $rootScope.$new()
$controller = _$controller_
$controller('firstController', { '$rootScope' : $rootScope, '$scope' : $scope })
});
});
describe('when message 1', function(){
beforeEach(function(){
serviceData.message = 'I am message one' // that way, you modify the object that your 'ServiceData' provider holds.
});
it('should get data from a service', function(){
expect($scope.serviceData.message).toEqual( '1' )
});
});
describe('when message 2', function(){
beforeEach(function(){
serviceData.message = 'I am message two'
});
it('should get data from a service', function(){
expect($scope.serviceData.message).toEqual( '2' )
});
});
});
免责声明:我不能100%确定$PROFECT.value的内部工作原理。如果上述操作不起作用,可能是因为$PROFECT.value函数的对象是在内部克隆的。为什么不在每次操作之前执行(函数(ServiceData){ServiceData.message='I am message two'})
@Chandermani你也需要inject()
你应该看看sinon的模仿/存根是正确的@james,我忘了那一部分。@james我已经看了sinon一小段……这允许我使用上下文吗?为什么不在每次(函数(ServiceData){ServiceData.message='i am message two')之前做;
@Chandermani你也需要inject()
你应该看看sinon的模仿/存根是正确的@james,i