42

我在我的主模板中定义了一个全局变量,我用它来存储来自后端的信息位,例如环境上下文路径。我无法在服务中移动该变量。

运行单元测试时,如何将该变量公开给 Karma?

4

3 回答 3

69

您可以在测试文件中声明该全局变量:

var global = "something";

describe('Your test suit', function() {
...
});

或在您的文件中添加一个 Javascriptkarma.conf.js文件:

// list of files / patterns to load in the browser
files: [
   ...,
   'file-containing-the-global-variable.js'
],
于 2013-10-09T05:22:47.893 回答
14

如果您来自 Angular 2+,我发现可行的唯一方法是使用以下方法全局创建变量或对象window

从脚本加载的 Google Recapthca:

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>

在此示例中,调用 google Recaptcha 将创建一个名为grecaptcha.

在我们的组件中,我们决定渲染一个新的 Google Recaptcha。当然,由于我们没有声明grecaptcha,我们需要使用declare var说 hey I promise 它在某处声明:

declare var grecaptcha;

private CreateGoogleCaptcha() {
  grecaptcha.render('recaptcha', {
    sitekey: this.siteKey,
    callback: this.GoogleCaptchaCallback,
    badge: 'inline'
  });
}

private GoogleCaptchaCallback(token) {
   // Handle Callback Logic
}

现在我们的函数工作了,我们决定运行一个测试,但当然我们想模拟我们的grecaptcha,因为我们无法控制它。所以我们命名我们想要创建的全局变量并添加我们想要的函数:

beforeEach(() => {
  fixture = TestBed.createComponent(GoogleRecaptchaComponent);
  component = fixture.componentInstance;

  window['grecaptcha'] = {
    render() {
      console.log('mocked global variable and function');
    }
  }
}

更新:

在 中创建全局变量beforeEach很好,但是当它有某种回调函数(例如上面)从您的组件调用函数时呢?很简单,我们只需将登录名移到我们的测试中,并在我们的模拟中将其设置为我们的组件函数:

it('should ', () => {
  window['grecaptcha'] = {
    render: function() { GoogleRecaptchaComponent['GoogleCaptchaCallback']('token'); }
  };

  spyOn<any>(GoogleRecaptchaComponent, 'GoogleCaptchaCallback');

  GoogleRecaptchaComponent['CreateGoogleCaptcha']();
  expect(GoogleRecaptchaComponent['GoogleCaptchaCallback']).toHaveBeenCalled();
});

注意: spyOn<any> :<any>是因为它是私有的,所以我们可以正确引用该函数,否则我们会得到一个打字稿错误;

于 2018-11-23T20:42:04.457 回答
6

第一个解决方案在 Angular 2.1.x 中对我不起作用。它根本无法识别我导入的服务中的变量。我要做的就是将我的环境变量放在我的karma-test-shim.js文件中并删除var,以便它可以在全球范围内使用。

我的看起来像这样:

Error.stackTraceLimit = Infinity;

require('core-js/es6');
require('reflect-metadata');

require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy'),
require('zone.js/dist/sync-test'),
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');

// Add environment variables here so that tests will inject them in source code
API_URL = 'http://localhost:8080/api/';

var appContext = require.context('../src', true, /\.spec\.ts/);

appContext.keys().forEach(appContext);

var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');

testing.TestBed.initTestEnvironment(
    browser.BrowserDynamicTestingModule,
    browser.platformBrowserDynamicTesting()
);
于 2016-11-18T20:02:23.723 回答