我想提供简单的常量值,例如姓名,电子邮件等,以便在我的茉莉花单元测试中使用。
此处提出了类似的问题:AngularJS + Karma: reuse a mock service when unit testing directives or controllers
在c#中,我将创建一个静态类来保存模拟数据的小片段。然后我可以在整个单元测试中使用这些值,如下所示:
static class SampleData
{
public const string Guid = "0e3ae555-9fc7-4b89-9ea4-a8b63097c50a";
public const string Password = "3Qr}b7_N$yZ6";
public const string InvalidGuid = "[invalid-guid]";
public const string InvalidPassword = "[invalid-password]";
}
使用Karma / Jasmine测试我的AngularJS应用程序时,我希望有同样的便利。
我知道我可以针对我的角度应用程序定义一个constant
对象,我已经针对我在真实代码中使用的常量执行此操作,如下所示:
myApp.constant('config', {apiUrl:'http://localhost:8082'})
我可以像这样添加另一个常量,但只包含用于我的单元测试的样本数据值,如下所示:
myApp.constant('sampleData', {email: 'sample@email.com'})
然后我可以将模拟常量对象注入到我的测试中,然后我就这样了,就像这样
describe 'A sample unit test', ->
beforeEach -> module 'myApp'
beforeEach inject ($injector) ->
@sampleData = $injector.get 'sampleData'
email = @sampleData.email
# etc ...
然而这对我来说似乎有点可疑。我不希望我的生产代码包含仅我的单元测试所需的样本数据。
您如何通过可重复使用的样品数据值方便地提供角度/茉莉花单位测试?
由于
答案 0 :(得分:9)
有两种方法可以做到这一点:
当你只需假一些电话时,第一个就好了。为全班做这件事是不可持续的。
例如,假设您有一个构建一些特殊URL的服务。如果其中一个方法依赖于absUrl,你可以通过监视$location
对象中的方法伪造它:
describe('example') function () {
beforeEach(inject(function () {
spyOn($location, 'absUrl').andCallFake(function (p) {
return 'http://localhost/app/index.html#/chickenurl';
});
}));
it('should return the url http://www.chicken.org') ... {
// starting situation
// run the function
// asserts
}
现在假设你有一个Settings
服务,它封装了语言,主题,特殊路径,背景颜色,字体等数据,这些数据是使用对服务器的远程调用初始化的。
依赖Settings
的测试服务会很痛苦。你必须每次都用spyOn模拟一个大的组件。如果你有10个服务......你不想在所有服务中复制spyOn函数。
ServiceA
使用Settings
服务:
describe('ServiceA', function () {
var settings, serviceA;
beforeEach(module('myapp.mocks.settings')); // mock settings
beforeEach(module('myapp.services.serviceA')); // load the service being tested
beforeEach(inject(function (_serviceA_, _settings_) {
serviceA = _serviceA_;
settings = _settings_;
}));
容器
对于此测试套件,对Settings
服务的所有调用都将由模拟处理,模拟具有与实际相同的接口,但返回虚拟值。
请注意,您可以在任何地方加载此服务。
(如果由于任何原因,你需要使用真正的实现,你可以在模拟之前加载真实的实现,并使用spyOn为特定的情况委托调用实际的实现。)
通常你会将mocks模块放在app文件夹之外。我有一个带有单元测试的test
文件夹,e2e测试和带有angular-mocks.js文件的lib
文件夹。我也把我的嘲笑放在那里。
告诉karma测试所需的文件:
files: [
'app/lib/jquery/jquery-1.9.1.js',
'test/lib/jasmine-jquery.js',
'app/lib/angular/angular.js',
'app/lib/angular/angular-*.js',
'test/lib/angular/angular-mocks.js',
'test/lib/myapp/*.js', /* this is mine */
'app/js/**/*.js',
'test/unit/**/*.js'
],
文件tests/lib/myapp.mocks.settings.js
看起来就像任何其他模块一样:
(function () {
"use strict";
var m = angular.module('myapp.mocks.settings', []);
m.service('settings', function () { ... })
})
第二个问题(可选):您想快速更改虚拟值。在该示例中,设置服务在第一次实例化时从服务器获取对象。然后,该服务具有所有字段的getter。这是服务器的代理:不是每次需要值时发送请求,而是获取一堆请求并在本地保存。在我的应用程序中,设置在运行时不会在服务器中更改。
类似的东西:
1. fetch http://example.org/api/settings
2. var localSettings = fetchedSettings;
3 getFieldA: function() { return localSettings.fieldA; }
去污染全局命名空间。我创建了一个文件settings.data.js
,内容如下:
var SETTINGS_RESPONSE = { fieldA: 42 };
模拟服务在工厂中使用此全局变量来实例化localSettings