javascript 使用Jasmine和TypeScript进行单元测试

scyqe7ek  于 9个月前  发布在  Java
关注(0)|答案(9)|浏览(136)

我试图使用Jasmine编译一个用Typescript编写的单元测试。在我的单元测试文件中有以下内容,Resharper提示我从jasmine. d. ts导入类型的链接。

/// <reference path="sut.ts" />
/// <reference path="../../../scripts/typings/jasmine/jasmine.d.ts" />

describe("Person FullName", function () {
    var person;

    BeforeEach(function () {
        person = new Person();
        person.setFirstName("Joe");
        person.setLastName("Smith");
    });

    It("should concatenate first and last names", function () {
        Expect(person.getFullName()).toBe("Joe, Smith");
    });
});

字符串
所以我点击链接,最后得到以下结果(实际上,resharper只给describe函数加上了“Jasmine."前缀,所以我手动给其他Jasmine调用加上了前缀):

/// <reference path="sut.ts" />
/// <reference path="../../../scripts/typings/jasmine/jasmine.d.ts" />
import Jasmine = require("../../../Scripts/typings/jasmine/jasmine");

Jasmine.describe("Person FullName", function () {
    var person;

    Jasmine.BeforeEach(function () {
        person = new Person();
        person.setFirstName("Joe");
        person.setLastName("Smith");
    });

    Jasmine.It("should concatenate first and last names", function () {
        Jasmine.Expect(person.getFullName()).toBe("Joe, Smith");
    });
});


但是,导入语句有一条红色的波浪线,并显示错误消息“无法解析外部模块../scripts/typings/jasmine/jasmine。模块不能别名为非模块类型”。
任何想法是什么导致这个错误?我已经检查了“模块系统”选项设置为AMD在我的项目构建设置.我还检查了茉莉花模块定义在jasmine. d. ts.我下载了这个文件从martelyTyped网站.

declare module jasmine {
    ...
}

ljsrvy3e

ljsrvy3e1#

以下是(在我看来)截至2018年测试ts-node应用程序的最佳方法:

npm install --save-dev typescript jasmine @types/jasmine ts-node

字符串
package.json中:

{
  "scripts": {
    "test": "ts-node node_modules/jasmine/bin/jasmine"
  }
}


jasmine.json中,将文件模式更改为*.ts

"spec_files": ["**/*[sS]pec.ts"],


在spec文件中:

import "jasmine";
import something from "../src/something";

describe("something", () => {
    it("should work", () => {
        expect(something.works()).toBe(true);
    });
});


要运行测试,请执行以下操作:

npm test


这将使用本地安装的ts-nodejasmine版本。这比使用全局安装的版本更好,因为使用本地版本,您可以确保每个人都使用相同的版本。
注意:如果你有一个Web应用程序而不是节点应用程序,你可能应该使用Karma而不是Jasmine CLI来运行测试。

dffbzjpn

dffbzjpn2#

把它放在你的typescript spec文件的顶部:

/// <reference path="../../node_modules/@types/jasmine/index.d.ts" />
let Jasmine = require('jasmine');

字符串
您必须安装以下Jasmine模块才能正常工作:

$ npm install jasmine-core jasmine @types/jasmine @ert78gb/jasmine-ts --save-dev


完成此操作后,IDE(如WebStorm)将识别Jasmine及其函数,如describe()、it()和expect()。因此,您不需要在它们前面加上“Jasmine”前缀。此外,您可以使用jasmine-ts模块从命令行运行spec文件。全局安装以下命令行工具:

$ npm install -g jasmine @ert78gb/jasmine-ts


然后配置“jasmine”命令行模块,以便Jasmine可以找到它的配置文件。然后您应该能够运行jasmine-ts,并且您的spec文件应该可以从命令行正常运行:

./node_modules/.bin/jasmine-ts src/something.spec.ts


..而且,你也可以配置你的IDE来运行它,这样运行调试也应该可以(对我来说很有效)。
以这种方式编写测试,您可以在服务器端运行Jasmine测试规范而无需Karma,也可以使用Karma在Web浏览器中运行它。相同的类型脚本代码。

cwtwac6a

cwtwac6a3#

如果您有导入问题,请使用tsconfig-paths

npm i ts-node tsconfig-paths types/jasmine jasmine --save-dev

字符串
运行启用了类型脚本的jasmine:

ts-node -r tsconfig-paths/register node_modules/jasmine/bin/jasmine.js


确保您的jasmine将搜索.ts文件:

"spec_files": [
    "**/*[sS]pec.ts"
],
"helpers": [
    "helpers/**/*.ts"
],


要测试脚本,如果在项目中使用了polyfill,可能还需要使用它们。

import 'core-js';

rggaifut

rggaifut4#

对我来说,我做了以下事情:
安装类型

npm install typings --global

字符串
然后把jasmine的打字加进去

typings install dt~jasmine --save --global

ogq8wdun

ogq8wdun5#

你可以尝试一个side-effect only import,它引入了@types/jasmine声明,并将jasmine函数置于全局作用域中,这样你就不需要在每个调用之前加上jasmine.,从而允许从现有的单元测试中快速移植,并且仍然可以很好地使用webpack。

// tslint:disable-next-line:no-import-side-effect
import "jasmine";

describe("My Unit Test", () => { /* ... */ } );

字符串
当然,你仍然需要安装jasmine和打字:

$ npm i jasmine @types/jasmine --save-dev


但是不需要专门的jasmine加载器来加载ts或node。只需对编译后的js文件运行jasmine即可:

$ node ./node_modules/jasmine/bin/jasmine.js --config=test/support/jasmine.json


假设你的打字脚本文件在一个编译为bin/test的“测试”脚本中,你有一个test/support/jasmine.json,它类似于:

{
    "spec_dir": "bin/test",
    "spec_files": [
      "**/*[sS]pec.js"
    ],
    "stopSpecOnExpectationFailure": false,
    "random": false
}


P.S.所有上述作品在Windows太

pcrecxhr

pcrecxhr6#

包括这到您的茉莉html文件,.

<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/jasmine.js"></script>

字符串
.或者安装npm jasmine包:

npm install --save-dev jasmine


当你使用第二种方式(jasmine作为模块)时,你必须导入它:

var jasmine = require('jasmine');


import jasmine from 'jasmine';


然后更改另一个代码:

jasmine.describe("Person FullName", function () {
    var person;

    jasmine.beforeEach(function () {
        person = new Person();
        person.setFirstName("Joe");
        person.setLastName("Smith");
    });

    jasmine.it("should concatenate first and last names", function () {
        jasmine.expect(person.getFullName()).toBe("Joe, Smith");
    });
});


就我个人而言,我更喜欢第一种方式,而不使用jasmine npm模块。(我还没有测试该模块)

wlp8pajw

wlp8pajw7#

你并没有要求这样做,但是为了加分:一旦你得到了AJ的答案并运行(使用ts-node调用Jasmine启动脚本),你就可以添加一个新任务:

"scripts": {
  "watch": "ts-node-dev --respawn -- ./node_modules/jasmine/bin/jasmine src/**.spec.ts"
}

字符串
当然,如果你愿意的话,你可以使用Jasmine的配置文件来传递你的specs或者其他参数。现在,Jasmine会运行你所有的specs一次,然后ts-node-dev会在后台等待你的测试或者任何他们可能需要require修改的东西。我还没有找到一种方法来只运行已经改变的测试(或者导入已经改变的测试)--据我所知,那就是not supported anyway;

hxzsmxv2

hxzsmxv28#

我的文件夹结构

Spec文件夹位于项目的根目录下

spec
      \- dist              // compiled tests
      \- helpers           // files modified testing env
         \- ts-console.ts  // pretty prints of results
      \- support
         \- jasmine.json
      \- YourTestHere.spec.ts
      \- tsconfig.json     // tsconfig for your tests

字符串

文件内容

ts-console.ts

const TSConsoleReporter = require("jasmine-console-reporter");
jasmine.getEnv().clearReporters();
jasmine.getEnv().addReporter(new TSConsoleReporter());


jasmine.json**

{
  "spec_dir": "spec/dist",
  "spec_files": [
     "**/*[sS]pec.js"
  ],
  "helpers": [
    "spec/helpers/**/*.js"
  ],
  "stopSpecOnExpectationFailure": false,
  "random": true
}

package.json中有额外的脚本

"scripts": {
  "test": "rm -rf ./spec/dist && tsc -p ./spec && jasmine"
}


并将行“/spec/dist”添加到**.gitignore**

运行您的测试!

使用npm test运行测试。

它是如何工作的?

1.已清理测试目录。
1.测试被编译到spec/dist文件夹到JS。
1.测试从此位置运行。

  • 希望对你有帮助,编码很好 *
jmo0nnb3

jmo0nnb39#

投票最高的答案是90%,但它忽略了一个可能影响您的关键细节:它假设您的tsconfig.json“模块”设置为“CommonJS”。如果您有其他东西,如"module": "ES2020""module": "ESNext",您将在半天内与importrequire错误打地鼠。
你不需要改变整个项目的“模块”值来克服这些错误,你可以设置一个node-ts覆盖。这样,当node-ts运行时,项目将只为"module": "CommonJS"。有多种方法可以做到这一点,但我通过将以下内容添加到tsconfig.json文件的底部来实现:

...
  "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  }
}

字符串
无论如何,在设置jasmine和typescript方面有很多辛苦学习的问题,我认为值得分享一个 * 整个 * 工作项目。You can browse/clone it on github,我将在下面分享摘录:

项目结构

.
├── .eslintrc.json
├── .prettierrc
├── LICENSE
├── package.json
├── spec/
│   └── support/
│       ├── jasmine.json
│       ├── logger.js
│       ├── slow-spec-reporter.js
│       └── type-check.js
├── src/
│   ├── index.spec.ts
│   └── index.ts
├── tsconfig.json
├── tsconfig.src.json
├── tsconfig.test.json
└── tsup.config.ts

./package.json

{
  "name": "jasmine-ts-example",
  "description": "A working example of a TypeScript project using the Jasmine test framework.",
  "version": "0.0.1",
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "license": "MIT",
  "files": [
    "dist"
  ],
  "scripts": {
    "compile-typescript": "tsup",
    "build": "tsup",
    "test": "jasmine",
    "run": "npm run build && node dist/index.js"
  },
  "keywords": ["jasmine", "ts", "typescript", "node-ts"],
  "devDependencies": {
    "@types/jasmine": "^5.1.4",
    "@types/node": "^20.10.6",
    "@typescript-eslint/eslint-plugin": "^6.17.0",
    "eslint": "^8.56.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.1.2",
    "eslint-plugin-testcafe": "^0.2.1",
    "jasmine": "^5.1.0",
    "ts-node": "^10.9.2",
    "tslib": "^2.6.2",
    "tsup": "^8.0.1",
    "typescript": "^5.3.3"
  },
  "engines": {
    "node": ">=18"
  }
}

./spec/support/jasmine.json

{
  "spec_dir": "",
  "spec_files": ["**/*.spec.ts"],
  "helpers": [
    "spec/support/logger.js",
    "spec/support/type-check.js"
  ],
  "stopSpecOnExpectationFailure": false,
  "random": true
}

./spec/support/logger.js

jasmine.getEnv().addReporter({
  specDone: function (result) {
    if (result.status !== 'excluded') {
      console.log(result.fullName);
    }
  },
});

./spec/support/slow-spec-footer.js

// To enable, add as a helper in your jasmine config file
const slowSpecsReporter = {
    specStarted: function(result) {
      this.specStartTime = Date.now()
    },
    specDone: function(result) {
      const seconds = (Date.now() - this.specStartTime) / 1000
      if (seconds > 0.5) {
        console.log('WARNING - This spec took ' + seconds + ' seconds: "' + result.fullName + '"')
      }
    },
  }
jasmine.getEnv().addReporter(slowSpecsReporter);

./spec/support/type-check.js

require('ts-node').register({
  project: "tsconfig.json",
  transpileOnly: true,
  files: true
})

./tsv.json

{
  "compilerOptions": {
    /* Basic Options */
    "target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "lib": [
      "ESNext"
    ] /* Specify library files to be included in the compilation. */,
    "types": ["node", "jasmine"],
    "allowJs": false /* Allow javascript files to be compiled. */,
    "declaration": true /* Generates corresponding '.d.ts' file. */,
    "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
    "sourceMap": true /* Generates corresponding '.map' file. */,
    "outDir": "dist" /* Redirect output structure to the directory. */,
    "importHelpers": true /* Import emit helpers from 'tslib'. */,
    "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */,
    "strict": true /* Enable all strict type-checking options. */,
    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    "noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
    "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
    /* Module Resolution Options */
    "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
    "baseUrl": "." /* Base directory to resolve non-absolute module names. */,
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  },
  "references": [
    {
      "path": "./tsconfig.src.json"
    }
  ],
  "include": [],
  "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  }
}

./tsv.src.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "declaration": true,
    "composite": true
  },
  "include": ["./src/**/*.ts"],
  "exclude": ["./**/*.spec.ts"]
}

./tsv.test.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "declaration": true,
    "composite": true
  },
  "references": [
    {
      "path": "./tsconfig.src.json"
    }
  ],
  "include": ["./**/*.spec.ts", "./test/**/*.ts", "./tsup.config.ts"]
}

./src/index.spec.ts

import { myBool } from './index';

describe(`index`, () => {
  it(`passes`, () => {
    expect(myBool).toEqual(true);
  });
});

./src/index.ts

export const myBool = false;

相关问题