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

Front end javascript testing using Require and Resharper

因此,我一直在尝试弄清前端测试的工作方式(单元测试),但我在某些方面陷入困境。

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

1
2
3
4
5
6
7
8
9
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

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

1
2
3
4
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测试正常工作吗?

我确实设法通过控制台并使其与phantomjs和durandal测试文件结合使用define来工作,但我需要在控制台之外使用它,因此我无法使用此define,因为测试运行程序获得了胜利找不到我的测试。

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

人物模型

1
2
3
4
5
6
7
8
9
10
11
12
define([],
function () {
    var getTitle = function() {
        return"hello";
    }

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

更新

我可以使用代码,但不能使用reshaper。在durandal网页之后的页面。

但是这让我获得了控制台输出,该输出可以通过非结构化方式来实际读取。

但是我可以使用define关键字,然后它可以正常工作。所以我认为这是我弄乱某些东西的require关键字吗?

更新2

所以我用提琴手来检查发生了什么。我也终于使它工作了(有点...)。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
///<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文件:

1
2
3
4
5
6
define("people", ["bla"], function (bla) {
    return {
        title: 'People page',
        bla: bla
    };
});

正如您在此处看到的,我将我的视图模型命名为people
这适用于testrunner,但他实际上并没有通过requireJS获得任何文件,而是仅通过引用路径获得任何文件。同样,这不符合我的需求,因为未指定durandal模型。

提琴手截图:

Fiddler

确定要检查此帖子

这是我所做的:

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

1
2
3
4
5
6
define(['viewmodels/bla'], function (bla) {
    return {
        title: 'People page',
        bla: bla //testing dependencies on other viewmodels
    };
});

然后我也做了bla.js

1
2
3
4
5
define(function() {
    return {
       bla:"bla"
    };
});

现在进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();
    });
});
});

然后,最终,阅读顶部提供的链接上的答案,我必须创建一个Chutzpah配置文件来创建测试harnass:

1
2
3
4
5
6
7
8
9
10
11
12
{
  "Framework":"jasmine",
  "TestHarnessReferenceMode":"AMD",
  "TestHarnessLocationMode":"SettingsFileAdjacent",
  "References" : [
       {"Path" :"../Scripts/require.js" },
       {"Path" :"requireConfig.js" }
   ],
  "Tests" : [
     {"Path":"specs"}
   ]
}

现在,使用Visual Studio测试运行器运行测试实际上可以为我提供所需的一切,如您所见,我现在可以通过require这样访问我的所有视图模型:require(['viewmodels/whateverviewmodel'], function(whateverviewmodel){....})

我希望这个答案可以帮助人们使用Jasmine和RequireJS测试您的(Durandal)SPA。

我知道我的观点模型在这个答案中,或者在问题本身中,都说了很多,但这应该使您知道如何进行所有这些操作。

小型编辑

您现在还可以在测试内部使用require([] ...跳过回调混乱,并像使用define

进行viewmodel一样构建测试

1
2
3
4
5
6
7
8
9
10
11
12
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');
        });
    });
});

这样可以减少缩进量,并且可读性强。


RequireJS提供的require调用本质上是异步的,因此您需要执行以下操作:

1
2
3
4
5
6
7
it('returns true', function (done) {
    require(["people"], function(people) {
        expect(people.getTitle()).toBe('People piolmjage');

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

您在问题中显示的第一次尝试无效。这就是经典的"试图从异步代码中同步返回值"的错误。使用require("people")的第二次尝试也不起作用,因为此require调用是伪同步的,并且仅在请求的模块已加载时才起作用。有关此伪同步require的工作原理的说明,请参见此答案。