使用 Require 和 Resharper 进行前端 javascript 测试

Front end javascript testing using Require and Resharper

所以我一直在试图弄清楚前端测试是如何工作的(单元测试),但我在某个点上卡住了。

所以我的 jasmine 测试设置如下:

describe('Blabla', function () {

    it('returns true', function () {
        var people = require(["people"], function(ppl) {
            return ppl;
        });
        expect(people.getTitle()).toBe('People piolmjage');
    });
});

但是运行这让我:

TypeError: undefined is not a funtion

很明显,人是不确定的。所以也许我的回调来得太晚了。但是,如果我删除回调,则会出现以下错误:

it('returns true', function () {
    var people = require("people");
    expect(people.getTitle()).toBe('People piolmjage');
});

Error: Module name "people" has not been loaded yet for context: _. Use require([])

我觉得我的设置有问题...有人知道如何让这个 FE 测试起作用吗?

我确实设法让它从控制台工作,并使用 define 结合 phantomjs 和 durandal 测试文件,但我需要它在控制台之外工作,因此我不能使用它 define 因为测试运行器找不到我的测试。

这就是为什么我需要使用 CommonJS 来获取所需的视图模型。

人模

define([],
function () {
    var getTitle = function() {
        return "hello";
    }

    var peopleViewModel = {
        title: 'People page',
        getTitle: getTitle
    };
    return peopleViewModel;
});

更新

我的代码可以正常工作,但 不能 使用 resharper。关注 this page from the durandal webpage.

但这让我得到了控制台输出,这是一种非结构化的方式来实际阅读。

但是我可以使用 define 关键字然后它工作正常。所以我假设是 require 关键字让我搞砸了什么?

更新 2

所以我用fiddler来查看是怎么回事。我也终于让它工作了(有点......)。

我的测试文件现在看起来像这样:

///<reference path="../../Scripts/require.js"/>
///<reference path="../../test/lib/jasmine-2.1.3/jasmine.js"/>

///<reference path="../../App/viewmodels/people.js"/>

describe('Blabla', function () {
    it('require test', function (done) {
        require(['people'], function (people) {
            expect(people.title).toBe('People page');
            done();
        });
    });
});

然后我更改了 people 文件:

define("people", ["bla"], function (bla) {
    return {
        title: 'People page',
        bla: bla
    };
});

如您所见,我将我的视图模型命名为people。 这适用于测试运行者,但他实际上并没有通过 requireJS 获取任何文件,而只是获取参考路径。这也不符合我的需要,因为 durandal 模型是 unnamed.

Fiddler 屏幕截图:

所以基本上他不使用 requireJS 来获取视图模型,因此我不能只使用 require.config 初始化程序来进入我的 viewmodels 文件夹并使用 requireJS 下载每个视图模型。有什么想法吗?

RequireJS 提供的 require 调用是 固有的 异步的,所以你需要做这样的事情:

it('returns true', function (done) {
    require(["people"], function(people) {
        expect(people.getTitle()).toBe('People piolmjage');

        done(); // Signal that the test is done.
    });
});

您在问题中显示的第一次尝试无效。这是典型的 "trying to return values synchronously form asynchronous code" 错误。 require("people") 的第二次尝试也不起作用,因为此 require 调用是伪同步的,并且仅当请求的模块已 已经 加载时才会起作用。有关此伪同步 require 工作原理的说明,请参阅 this answer

我终于让它工作了,花了我一天半的时间。

反正我已经不用resharper了,准确点说是test runner。 Chutzpah 是我最后求助的那个。这也让我进行了一些研究,但我已经达到了它包含我想要的所有内容的地步。

Check this post for sure

这是我所做的:

我的people.js看起来像这样:

define(['viewmodels/bla'], function (bla) {
    return {
        title: 'People page',
        bla: bla //testing dependencies on other viewmodels
    };
});

然后我也做了一个bla.js

define(function() {
    return {
       bla: "bla"
    };
});

现在进行测试:

describe('Blabla', function () {
it('require test', function (done) {
    require(['viewmodels/people'], function (people) {
        expect(people.title).toBe('People page');
        done();
    });
});

it('dependency on require test', function (done) {
    require(['viewmodels/people'], function (people) {
        console.log(people.bla);
        expect(people.bla.bla).toBe('bla');
        done();
    });
});
});

最后,阅读顶部提供的 link 上的答案,我不得不创建一个 Chutzpah 配置文件来创建一个测试 harnass:

{
   "Framework": "jasmine",
   "TestHarnessReferenceMode": "AMD",
   "TestHarnessLocationMode": "SettingsFileAdjacent",
   "References" : [
       {"Path" : "../Scripts/require.js" }, 
       {"Path" : "requireConfig.js" }
   ],
   "Tests" : [
     {"Path": "specs"}
   ]
}

现在,运行 Visual studio 测试运行器 的测试实际上得到了我需要的一切,正如你所看到的,我现在可以访问我所有的viewmodels 通过 require 像这样:require(['viewmodels/whateverviewmodel'], function(whateverviewmodel){....})

我希望这个答案能让人们开始使用 Jasmine 和 RequireJS 测试您的 (Durandal)SPA。

我知道我在这个答案中的视图模型,也不在问题本身中,说了很多,但这应该让您了解如何处理所有这些问题。

小编辑

您现在还可以跳过测试中使用 require([]... 的回调混乱,并 像使用视图模型一样构建测试define

define(['viewmodels/people'], function (people) {
    describe('Blabla', function () {
        it('require test', function () {
            expect(people.title).toBe('People page');
        });

        it('dependency on require test', function () {
            console.log(people.bla);
            expect(people.bla.bla).toBe('bla');
        });
    });
});

这样可以减少缩进,并且本身更具可读性。