【问题标题】:Angular Jasmine Test HTML Injection FailsAngular Jasmine 测试 HTML 注入失败
【发布时间】:2017-12-25 09:25:30
【问题描述】:

我无法将我的 HTML 模板注入我的 Jasmine 测试。如何解决此错误?

错误:此测试模块使用了使用“templateUrl”或“styleUrls”的组件 FooDetailComponent,但它们从未被编译。请在测试前调用“TestBed.compileComponents”。

我的测试清楚地调用了compileComponents(),并且还设置了templateUrl,所以我不清楚如何进行。

foo-detail.component.ts定义:

@Component({
    selector: 'my-selector',
    templateUrl: './foo-detail.component.html'
})
export class FooDetailComponent implements OnInit, OnDestroy { ... }

foo-detail.component.spec.ts:

describe('Component Tests', () => {

    describe('Foo Management Detail Component', () => {
        let comp: FooDetailComponent;
        let fixture: ComponentFixture<FooDetailComponent>;
        let service: FooService;

        beforeEach(async(() => {
            TestBed.configureTestingModule({
                declarations: [FooDetailComponent],
                providers: [
                    MockBackend,
                    BaseRequestOptions,
                    {
                        provide: Router,
                        useClass: class { navigate = jasmine.createSpy("navigate"); }
                    },
                    FooService
                ]
            }).overrideComponent(FooDetailComponent, {
                set: {
                      // This line, when uncommmented, allows the test to run, but 
                      //  doesn't recognize a template:
                    // template: ''
                      // This line, when uncommented, induces the error:
                    templateUrl : '../../../../../../main/webapp/app/entities/foo/foo-detail.component.html',
                    styleUrls: ['../../../../../../main/webapp/app/entities/foo/foo-create.scss']
                }
            }).compileComponents();
        }));

        beforeEach(() => {
            fixture = TestBed.createComponent(FooDetailComponent);
            comp = fixture.componentInstance;
            service = fixture.debugElement.injector.get(FooService);
        });


        describe('OnInit', () => {
            it('Should call load all on init', () => {
            // GIVEN
            spyOn(service, 'find');
            // WHEN
            comp.ngOnInit();
            // THEN
            service.find("testidentifier");
            expect(service.find).toHaveBeenCalledWith("testidentifier");
            });
        });
    });

});

全栈跟踪

Failed: Uncaught (in promise): Failed to load %3Cdiv%20id=%22%7B%7Bid%7D%7D <entire htmlenoded template>
resolvePromise@spec/entry.ts:110657:78
resolvePromise@spec/entry.ts:110627:31
spec/entry.ts:110704:31
invokeTask@spec/entry.ts:110310:36
onInvokeTask@spec/entry.ts:109806:49
invokeTask@spec/entry.ts:110309:48
runTask@spec/entry.ts:110077:57
drainMicroTaskQueue@spec/entry.ts:110470:42
run@spec/entry.ts:133028:29
spec/entry.ts:133041:31
flush@spec/entry.ts:59106:11
Error: This test module uses the component FooCreateComponent which is using a "templateUrl" or "styleUrls", but they were never compiled. Please call "TestBed.compileComponents" before your test. in spec/entry.ts (line 10169)
_initIfNeeded@spec/entry.ts:10169:91
createComponent@spec/entry.ts:10247:31
createComponent@spec/entry.ts:10076:48
spec/entry.ts:85022:56
invoke@spec/entry.ts:110277:31
onInvoke@spec/entry.ts:109782:45
invoke@spec/entry.ts:110276:40
run@spec/entry.ts:110027:49
spec/entry.ts:109481:37
spec/entry.ts:9456:34
spec/entry.ts:9503:33
invoke@spec/entry.ts:110277:31
onInvoke@spec/entry.ts:109020:45
onInvoke@spec/entry.ts:109779:47
invoke@spec/entry.ts:110276:40
run@spec/entry.ts:110027:49
spec/entry.ts:9498:32
onHandleError@spec/entry.ts:109030:31
onHandleError@spec/entry.ts:109787:52
handleError@spec/entry.ts:110281:50
runGuarded@spec/entry.ts:110043:55
_loop_1@spec/entry.ts:110539:57
microtaskDrainDone@spec/entry.ts:110548:24
drainMicroTaskQueue@spec/entry.ts:110478:36
run@spec/entry.ts:133028:29
spec/entry.ts:133041:31
flush@spec/entry.ts:59106:11
Error: <spyOn> : could not find an object to spy upon for create()
Usage: spyOn(<object>, <methodName>) in /myHomeDir/portal-frontend/node_modules/jasmine-core/lib/jasmine-core/jasmine.js (line 2067)
spec/entry.ts:85032:22
invoke@spec/entry.ts:110277:31
onInvoke@spec/entry.ts:109782:45
invoke@spec/entry.ts:110276:40
run@spec/entry.ts:110027:49
spec/entry.ts:109481:37
spec/entry.ts:9456:34
spec/entry.ts:9503:33
invoke@spec/entry.ts:110277:31
onInvoke@spec/entry.ts:109020:45
onInvoke@spec/entry.ts:109779:47
invoke@spec/entry.ts:110276:40
run@spec/entry.ts:110027:49
spec/entry.ts:9498:32
onHandleError@spec/entry.ts:109030:31
onHandleError@spec/entry.ts:109787:52
handleError@spec/entry.ts:110281:50
runGuarded@spec/entry.ts:110043:55
_loop_1@spec/entry.ts:110539:57
microtaskDrainDone@spec/entry.ts:110548:24
drainMicroTaskQueue@spec/entry.ts:110478:36
run@spec/entry.ts:133028:29
spec/entry.ts:133041:31
flush@spec/entry.ts:59106:11

堆栈:

  • Angular 2.4.4
  • 打字稿 2.1.5
  • 茉莉花芯2.5.2
  • 节点:">=7.5.0"
  • JHipster 4.5.2

【问题讨论】:

  • 如果你能为此提供一个 plunker 会更好。
  • JHipster 只支持 LTS 版本的 Node,你试过在 node 6.x 上运行吗?
  • @GaëlMarziou 如果这与 JHipster 有关,它将证明服务器 + 客户端脚手架工具是一个坏主意。你为什么使用旧版本的 TypeScript? JJ Zabkar,另外,您是否验证了相对于测试文件的路径存在?
  • @AluanHaddad 是的,相对路径存在。即使在我的 IDE 自动填充它之后,也要仔细检查它。
  • @AluanHaddad 我同意;生成的代码有点笨拙。我希望删除一些粗略的部分,以尝试更多地暴露关键部分;感谢您的反馈。

标签: node.js angular typescript jasmine jhipster


【解决方案1】:

感谢@DBosley 和@AluanHaddad 解决了这个问题。这是我所做的:

  1. 按照@DBosley 的建议重构我的代码以使用then 模式。

  2. overrideComponent 内重新启用templateUrl

  3. 根据this modification found on Github 更新我的karma.conf.js,这会产生更具描述性的堆栈跟踪:

    Failed: Uncaught (in promise): Error: Template parse errors:
    'jhi-alert-error' is not a known element:
        1. If 'jhi-alert-error' is an Angular component, then verify that it is 
          part of this module.
        2. If 'jhi-alert-error' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA"
          to the '@NgModule.schemas' of this component to suppress this message. 
        ("</div>
            <hr>
            [ERROR ->]<jhi-alert-error></jhi-alert-error>
            <dl class="row">
            </dl>
        "): FooComponent@4:4
        Can't bind to 'routerLink' since it isn't a known property of 'button'. ("
    
            <button type="button"
                    [ERROR ->][routerLink]="['/', { outlets: { ..."
                "): FooComponent
    
  4. 通过在我的TestBed.configureTestingModuleproviders 部分添加模拟来修复缺少的N 个依赖项:

    (first time)
    Failed: Uncaught (in promise): Error: No provider for JhiAlertErrorComponent!
    (Nth time)
    Failed: Uncaught (in promise): Error: No provider for BarService!
    

【讨论】:

    【解决方案2】:

    我可能是错的,但我认为你在做不必要的工作。如果我正确阅读了您的测试配置,则说明您声明了要测试的组件,但随后您将使用自己的模板和样式表覆盖它。

    这个link 有一个很好的例子来解释你为什么要覆盖模板或样式。如果您使用的是.overrideComponent,并且您只是将样式和模板设置为已设置为在其@Component 装饰器中使用的文件,则无需对.overrideComponent 进行整个调用。

    为了解决夹具抱怨您的组件未编译的问题,我发现您在 .compileComponents() 之后缺少一个 .then() 调用

    根据该文档,我认为您可能想要这样的东西:

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [FooDetailComponent],
            providers: [
                MockBackend,
                BaseRequestOptions,
                {
                    provide: Router,
                    useClass: class { navigate = jasmine.createSpy("navigate"); }
                },
                FooService
            ]
        }).compileComponents().then(()=>{
            fixture = TestBed.createComponent(FooDetailComponent);
            comp = fixture.componentInstance;
            service = fixture.debugElement.injector.get(FooService);
        });
    }));
    

    如果您确实需要覆盖,只需复制/粘贴上述.then() 调用的内容并删除您的第二个beforeEach(),因为它是不必要的。

    【讨论】:

    • @Dhraz 感谢您的建议和示例代码。我试过你的代码,但我仍然收到Failed to load %3Cdiv(我的html模板)错误。我不确定如何确定我的 HTML 模板有什么问题,或者这是否是问题所在。
    • 我以前从未遇到过该错误。我需要查看您的模板(或具有相同问题的简化模板)以查看其中是否存在问题。我已经使用与此几乎相同的测试台设置包装了 15-20 个组件,并且从未遇到过像您遇到的问题。
    • 更新!看起来目标电子邮件模板有一些其他(未注入的)自定义指令,但我不确定注入或模拟它们的正确方法。
    • @JJZabkar 我用它来模拟我不想在单元测试中运行的组件:medium.com/@cnunciato/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    相关资源
    最近更新 更多