测试模块无法解析正在测试的模块 [Angular4、Karma、Jasmine]

Test module can't resolve module being tested [Angular4, Karma, Jasmine]

我创建了一个小型 TypeScript 应用作为演示项目。它使用 Angular 4、Karma、Webpack 2 和 Jasmine。

应用程序构建成功,我可以在浏览器中 运行 它。

测试不起作用,当我在命令行中 运行 karma start 时,我看到这样的消息:

ERROR in ./app/welcome/app.welcome.spec.ts Module not found: Error: Can't resolve './app.welcome' in 'D:\ng-ts-demo\app\welcome'
@ ./app/welcome/app.welcome.spec.ts 4:20-44
@ ./app .spec.ts
@ ./app/test-main.ts

奇怪的是,app.welcome.ts 文件与 app.welcome.spec.ts 在同一目录中,但仍然找不到!从消息看来,问题是由于 test-main.ts 文件未加载 *.ts 文件,仅加载 *.spec.ts 文件引起的。

我已经遵循了官方 Angular 4/Webpack 指南 here,我似乎没有遗漏任何重要的东西。

这是我的测试-main.ts 文件:

Error['stackTraceLimit'] = Infinity;

import 'core-js/es7/reflect';
import 'reflect-metadata';
import 'zone.js';
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/proxy';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';

import { TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';

let appContext = require.context('./', true, /\.spec\.ts/); // is this line the problem?

appContext.keys().forEach(appContext);

TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());

这是我的 Karma.conf.js 文件:

'use strict';

const webpack = require('webpack');

module.exports = function(config) {
    config.set({

        basePath: '',
        frameworks: ['jasmine'],
        files: [
            { pattern: './app/test-main.ts' }
        ],
        exclude: [],
        preprocessors: {
            './app/test-main.ts': ['webpack', 'sourcemap']
        },
        reporters: ['progress'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: false,
        browsers: ['ChromeHeadless'],
        customLaunchers: {
            ChromeHeadless: {
                base: 'Chrome',
                flags: [
                  '--headless',
                  '--remote-debugging-port=9222',
                  '--disable-gpu',
                  '--disable-plugins',
                  '--window-size=0,0',
                  '--window-position=-9999,0'
                ],
            },
        },
        singleRun: true,
        concurrency: Infinity,
        webpack: {
            module: {
                rules: [{
                    test: /\.ts$/,
                    use: [
                        {
                            loader: 'awesome-typescript-loader',
                            options: {
                                configFileName: './tsconfig.json'
                            }
                        },
                        'angular2-template-loader'
                    ]
                }]
            },
            devtool: 'inline-source-map',
            plugins: [
                new webpack.ContextReplacementPlugin(/angular(\|\/)core(\|\/)@angular/, './app')
            ]
        },
        webpackMiddleware: {
            stats: 'errors-only'
        },
        webpackServer: {
            noInfo: true
        }
    });
}

这是 app.welcome.spec.ts 文件:

import { TestBed }            from '@angular/core/testing';
import { WelcomeComponent }   from './app.welcome';

describe('The Welcome component', function () {

    let component: WelcomeComponent;

    beforeEach(function() {
        TestBed.configureTestingModule({
            declarations: [WelcomeComponent]
        });

        let fixture = TestBed.createComponent(WelcomeComponent);
        component = fixture.componentInstance;
    });

    it('should be a component', function() {
        expect(component).toBeDefined();
    });

    it('should have a welcome message', function () {
        expect(component.welcomeMessage).toEqual('Welcome to TypeScript!');
    });

});

这里是 app.welcome.ts 模块(与 spec 文件在同一文件夹中,但神秘地找不到):

import { Component } from '@angular/core';

@Component({
    selector: 'my-app',
    template: '<h1>{{welcomeMessage}}</h1>',
})

export class WelcomeComponent {
    welcomeMessage = 'Welcome to TypeScript!';
}

要使这项工作正常进行,需要克服许多问题。第一个修复是在 karma.conf.js:

中的 webpack 配置中添加一个解析配置
resolve: {
    extensions: ['.js', '.ts']
},

这解决了我的测试文件无法导入他们正在测试的文件的问题。

这会导致第二个问题 - 测试文件本身没有被执行(当 运行 测试时,我可以在命令行输出中看到 Executed 0 of 0 ERROR。调试测试(通过设置singleRunfalse 并将浏览器从 ChromeHeadless 更改为常规 Chrome 在控制台中显示错误:

Refused to execute script from 'http://localhost:9876/base/test-main.ts' because its MIME type ('video/mp2t') is not executable.

这是一个影响 Chrome 55 岁以上的新问题,目前需要一个稍微复杂的修复程序;我必须将其添加到 karma.conf.js 文件(虽然不在 webpack 配置部分):

mime: {
    'text/x-typescript': ['ts']
}, 

此提示已在 this 期中选取。最后现在测试 运行 :)

现在也让报道工作...