如何为我的 angularjs/jasmine 单元测试提供可重用的样本数据值 [英] How do I provide re-usable sample data values to my angularjs / jasmine unit-tests

查看:8
本文介绍了如何为我的 angularjs/jasmine 单元测试提供可重用的样本数据值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想提供简单的常量值,例如姓名、电子邮件等,以便在我的 jasmine 单元测试中使用.

I would like to provide simple constant values such as names, emails, etc to use in my jasmine unit tests.

这里问了一个类似的问题:AngularJS +Karma:在单元测试指令或控制器时重用模拟服务

A similar question was asked here: AngularJS + Karma: reuse a mock service when unit testing directives or controllers

在 c# 中,我将创建一个静态类来保存模拟数据的小片段.然后我可以在整个单元测试中使用这些值,如下所示:

In c# I would create a static class to hold little snippets of mock data. I can then use these values throughout my unit tests, like this:

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 应用程序时获得同样的便利.

I would like to have the same convenience when testing my AngularJS app using Karma / Jasmine.

我知道我可以针对我的 Angular 应用程序定义一个 constant 对象,我已经为我在实际代码中使用的常量执行了此操作,如下所示:

I know that I can define a constant object against my angular app, I already do this for constants I use in the real code, like this:

myApp.constant('config', {apiUrl:'http://localhost:8082'})

我可以像这样添加另一个常量,但只包含用于我的单元测试的示例数据值,如下所示:

I could add another constant just like this but only containing sample data values for use in my unit tests, like this:

myApp.constant('sampleData', {email: 'sample@email.com'}) 

然后我可以将模拟常量对象注入到我的测试中,然后我就走了,就像这样

I could then just inject the mock constant object into my tests and off I go, like this

describe 'A sample unit test', ->
    beforeEach ->   module 'myApp'
    beforeEach inject ($injector) ->
        @sampleData = $injector.get 'sampleData'
        email = @sampleData.email
        # etc ...

然而,这对我来说似乎有点可疑.我不希望我的生产代码包含仅在我的单元测试中需要的示例数据.

However this seems a bit fishy to me. I don't want my production code to contain sample data that is only required by my unit-tests.

您将如何方便地为您的 angular/jasmine 单元测试提供可重复使用的样本数据值?

How would you conveniently provide your angular / jasmine unit tests with re-usable sample data values?

谢谢

推荐答案

有两种方法:

  • 监视函数调用并返回假值.
  • 创建模拟类(可能还有模拟数据来初始化它们)并在需要的地方加载它们

当您只需要伪造几个电话时,第一个就可以了.为整个班级这样做是不可持续的.

The first one is alright when you only have to fake a few calls. doing that for a whole class is unsustainable.

例如,假设您有一个构建一些特殊 URL 的服务.如果其中一种方法依赖于 absUrl,您可以通过监视 $location 对象中的方法来伪造它:

For example, let's say you have a service that builds some special URLs. If one of the methods depends on absUrl, you can fake it by spying on the method in the $location object:

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 功能.

Now let's say that you have a Settings Service that encapsulates data like language, theme, special paths, background color, typeface... that is initialised using a remote call to a server. Testing services that depend on Settings will be painful. You have to mock a big component with spyOn every time. If you have 10 services... you don't want to copypaste the spyOn functions in all of them.

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 服务的所有调用都将由 mock 处理,它与真实的接口具有相同的接口,但返回虚拟值.请注意,您可以在任何地方加载此服务.

container for this test suite, all calls to the Settings service will be handled by the mock, which has the same interface as the real one, but returns dummy values. Notice that you can load this service anywhere.

(如果出于任何原因,您需要使用真实的实现,您可以在模拟之前加载真实的实现,并针对特定情况使用 spyOn 将调用委托给真实的实现.)

(If, by any reason, you needed to use the real implementation, you can load the real implementation before the mock and use spyOn for that particular case to delegate the call to the real implementation.)

通常,您会将 mocks 模块放在 app 文件夹之外.我有一个带有单元测试、e2e 测试的 test 文件夹和一个带有 angular-mocks.js 文件的 lib 文件夹.我也把我的模拟放在那里.告诉 karma 测试所需的文件:

Normally you'll place the mocks module outside of the app folder. I have a test folder with the unit tests, e2e tests and a lib folder with the angular-mocks.js file. I place my mocks there too. Tell karma the files you need for the tests:

    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 看起来就像任何其他模块:

The file tests/lib/myapp.mocks.settings.js looks just like any other module:

(function () {
"use strict";

var m = angular.module('myapp.mocks.settings', []);

m.service('settings', function () { ... })
})

第二个问题(可选):您想快速更改虚拟值.在示例中,设置服务在第一次实例化时从服务器获取对象.然后,该服务具有所有领域的吸气剂.这是一种对服务器的代理:不是每次需要值时都发送请求,而是获取一堆并将它们保存在本地.在我的应用程序中,运行时服务器中的设置不会更改.

Second problem (optional): you want to change quickly the dummy values. In the example, the settings service fetches an object from the server when it is instantiated for the first time. then, the service has getters for all fields. This is kind of a proxy to the server: instead of sending a request everytime you need a value, fetch a bunch of them and save them locally. In my application, settings don't change in the server in run-time.

类似:

1. fetch http://example.org/api/settings
2. var localSettings = fetchedSettings;
3  getFieldA: function() { return localSettings.fieldA; }

去污染全局命名空间.我创建了一个文件 settings.data.js,其内容如下:

Go and pollute the global namespace. I created a file settings.data.js with a content like:

var SETTINGS_RESPONSE = { fieldA: 42 };

模拟服务在工厂中使用这个全局变量来实例化localSettings

the mock service uses this global variable in the factory to instantiate localSettings

这篇关于如何为我的 angularjs/jasmine 单元测试提供可重用的样本数据值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆