Angular 模拟缩小
Angular Mocks with minification
使命:
我有一个遗留的、未缩小的 Angular 1 个应用程序,经过数千次测试,全部通过。我在代码中引入了缩小和修改。如果我将库和应用程序代码分开,测试将继续进行。但是,我不能破坏应用程序代码,因为这样做会破坏合同回到 libs 文件。
我希望能够破坏应用程序代码并保持单元测试正常运行。
当前状态:
我已经创建了两条路径来规避这个问题,但我并不满意,因为单元测试并没有真正触及将在生产中使用的代码......它们触及了创建的中间地带避免处理问题。
路径 1
一个路径输出一个libs.min.js
和一个app.min.js
。 libs.min.js
内部是 Angular、Underscore 等内容 - 使用它们提供的缩小版本。本质上 libs.min.js
只是一堆已经缩小的文件连接在一起。 app.min.js
包含我们的应用程序代码,缩小但未损坏。
路径 2
第二个路径创建一个 combined.min.js
文件。这就是生产。在这个文件里面,依次是Angular、下划线等等,后面是我们的应用程序代码。所有这些都连接到这个文件 unminified(包括库),然后 mangled/minified 在一起,这样我们就可以获得一个源映射,它可以引用我们的应用程序代码以及库代码。这在浏览器中有效,但单元测试中断,因为 combined.min.js
不包含所需的仅测试库 angular-mocks
.
问题:
针对路径一的测试有效,因为 Karma 加载了这些文件。这很好,但它不是将要投入生产的实际代码,所以我不认为这是成功的。
- libs.min.js
- angular-mocks(未缩小 - 并且可以绑定到 Angular 因为我们使用的是提供的缩小版本)
- app.min.js(缩小但未被破坏,因为破坏破坏了合同回到 libs.min.js)
- *.spec.js
测试路径二不起作用,因为我们按以下顺序加载内容:
- combined.min.js
- angular-模拟(未缩小)
- *.spec.js
轰隆隆。我们的应用程序代码已经连接了它的绑定,所以 angular-mocks 来不及了。除了将库和应用程序加载到单独的文件中(如路径一)之外,我看不出有什么办法可以解决这个问题。
一些测试通过了,但是那些试图引用我们依赖的任何东西的测试都失败了angular-mocks。
我知道我可以向 app.min.js
提供一个输入源映射,这样我就可以 minify/mangle 应用单独编码(但始终反对 libs.min.js
),但我不是确定那是最好的路线。我想将所有内容保存在一个大文件中,但如果没有其他办法,我使用的库似乎 mangle/minify (UglifyJS) 支持输入源映射...
哦。此外,我们没有使用 Grunt 或 Gulp。只需直接使用 NPM 即可完成所有这些工作。但是,如果有 grunt 或 gulp 库可以以某种方式解决这个问题,我可以对其进行 NPM 化。
我想通了。最初的问题在诊断出什么问题时并不完全正确。我怀疑其他人是否会偶然发现此类问题,但为了以防万一,我会把它留在这里。
问题 1:
通过将库和应用程序一起缩小,我们要求一些库在严格模式下工作,而这些库原本不是严格模式。要么它们不在自执行函数中,要么存在从其他库泄漏的全局“use strict”...发生这种情况的原因有很多。
就我而言,罪犯是 Restangular。 1.4 版将无法在严格模式下工作,因为有一个隐式定义 'data'。我确定这是旧版本中的一个疏忽,但它会导致 Phantom 中出现关于“没有这样的 属性 'data'”的错误。
这很容易解决。最有可能的是,只需升级到更新的版本。此应用程序不允许升级到更新版本,所以现在我只是手动添加 'var data' 来欺骗定义。
问题 2:
我们的 Jasmine 测试开始失败。他们正在执行和使用缩小的代码。 运行 针对缩小代码时发生的情况的示例:
var result,
someObject = {foo: "bar"};
httpBackend.whenGET("/something").respond(someObject);
somethingService.then(function(response) {
result = response;
});
httpBackend.flush();
expect(result).toBe(someObject); // fail. {foo: "bar"} is not {route: "something", getRestangularUrl: function...}
通常这是可行的,因为 ngMocks 绕过了 Restangular 的响应包装器;您响应的对象将是传递给已解决承诺的对象,没有添加 Restangular 元数据。所以 {foo: "bar"}
仍然是 {foo: "bar"}
.
但是,由于我们在应用程序代码之后加载了 ngMocks(请参阅问题中的 'path 2'),Restangular 的响应不再被绕过。因此,Restangular 使用所有额外的元数据扩展了您的预期响应。
因此,我们的 {foo: "bar"}
变成了一个完整的 Restangular 响应,其中 包含 {foo: "bar"}
,但 不仅 [=43] =] {foo: "bar"}
.
解决方案:不要测试整个对象。检查特定键和该特定键的值。
var result;
httpBackend.whenGET("/something").respond({foo: "bar"});
somethingService.then(function(response) {
result = response;
});
httpBackend.flush();
expect(result.foo).toEqual("bar"); // pass
我认为以这种方式进行测试会更好,因为它更准确地表示一旦 ngMocks 消失后实际会发生什么。
使命:
我有一个遗留的、未缩小的 Angular 1 个应用程序,经过数千次测试,全部通过。我在代码中引入了缩小和修改。如果我将库和应用程序代码分开,测试将继续进行。但是,我不能破坏应用程序代码,因为这样做会破坏合同回到 libs 文件。
我希望能够破坏应用程序代码并保持单元测试正常运行。
当前状态:
我已经创建了两条路径来规避这个问题,但我并不满意,因为单元测试并没有真正触及将在生产中使用的代码......它们触及了创建的中间地带避免处理问题。
路径 1
一个路径输出一个libs.min.js
和一个app.min.js
。 libs.min.js
内部是 Angular、Underscore 等内容 - 使用它们提供的缩小版本。本质上 libs.min.js
只是一堆已经缩小的文件连接在一起。 app.min.js
包含我们的应用程序代码,缩小但未损坏。
路径 2
第二个路径创建一个 combined.min.js
文件。这就是生产。在这个文件里面,依次是Angular、下划线等等,后面是我们的应用程序代码。所有这些都连接到这个文件 unminified(包括库),然后 mangled/minified 在一起,这样我们就可以获得一个源映射,它可以引用我们的应用程序代码以及库代码。这在浏览器中有效,但单元测试中断,因为 combined.min.js
不包含所需的仅测试库 angular-mocks
.
问题:
针对路径一的测试有效,因为 Karma 加载了这些文件。这很好,但它不是将要投入生产的实际代码,所以我不认为这是成功的。
- libs.min.js
- angular-mocks(未缩小 - 并且可以绑定到 Angular 因为我们使用的是提供的缩小版本)
- app.min.js(缩小但未被破坏,因为破坏破坏了合同回到 libs.min.js)
- *.spec.js
测试路径二不起作用,因为我们按以下顺序加载内容:
- combined.min.js
- angular-模拟(未缩小)
- *.spec.js
轰隆隆。我们的应用程序代码已经连接了它的绑定,所以 angular-mocks 来不及了。除了将库和应用程序加载到单独的文件中(如路径一)之外,我看不出有什么办法可以解决这个问题。
一些测试通过了,但是那些试图引用我们依赖的任何东西的测试都失败了angular-mocks。
我知道我可以向 app.min.js
提供一个输入源映射,这样我就可以 minify/mangle 应用单独编码(但始终反对 libs.min.js
),但我不是确定那是最好的路线。我想将所有内容保存在一个大文件中,但如果没有其他办法,我使用的库似乎 mangle/minify (UglifyJS) 支持输入源映射...
哦。此外,我们没有使用 Grunt 或 Gulp。只需直接使用 NPM 即可完成所有这些工作。但是,如果有 grunt 或 gulp 库可以以某种方式解决这个问题,我可以对其进行 NPM 化。
我想通了。最初的问题在诊断出什么问题时并不完全正确。我怀疑其他人是否会偶然发现此类问题,但为了以防万一,我会把它留在这里。
问题 1:
通过将库和应用程序一起缩小,我们要求一些库在严格模式下工作,而这些库原本不是严格模式。要么它们不在自执行函数中,要么存在从其他库泄漏的全局“use strict”...发生这种情况的原因有很多。
就我而言,罪犯是 Restangular。 1.4 版将无法在严格模式下工作,因为有一个隐式定义 'data'。我确定这是旧版本中的一个疏忽,但它会导致 Phantom 中出现关于“没有这样的 属性 'data'”的错误。
这很容易解决。最有可能的是,只需升级到更新的版本。此应用程序不允许升级到更新版本,所以现在我只是手动添加 'var data' 来欺骗定义。
问题 2:
我们的 Jasmine 测试开始失败。他们正在执行和使用缩小的代码。 运行 针对缩小代码时发生的情况的示例:
var result,
someObject = {foo: "bar"};
httpBackend.whenGET("/something").respond(someObject);
somethingService.then(function(response) {
result = response;
});
httpBackend.flush();
expect(result).toBe(someObject); // fail. {foo: "bar"} is not {route: "something", getRestangularUrl: function...}
通常这是可行的,因为 ngMocks 绕过了 Restangular 的响应包装器;您响应的对象将是传递给已解决承诺的对象,没有添加 Restangular 元数据。所以 {foo: "bar"}
仍然是 {foo: "bar"}
.
但是,由于我们在应用程序代码之后加载了 ngMocks(请参阅问题中的 'path 2'),Restangular 的响应不再被绕过。因此,Restangular 使用所有额外的元数据扩展了您的预期响应。
因此,我们的 {foo: "bar"}
变成了一个完整的 Restangular 响应,其中 包含 {foo: "bar"}
,但 不仅 [=43] =] {foo: "bar"}
.
解决方案:不要测试整个对象。检查特定键和该特定键的值。
var result;
httpBackend.whenGET("/something").respond({foo: "bar"});
somethingService.then(function(response) {
result = response;
});
httpBackend.flush();
expect(result.foo).toEqual("bar"); // pass
我认为以这种方式进行测试会更好,因为它更准确地表示一旦 ngMocks 消失后实际会发生什么。