首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角使用Karma与茉莉花TypeError: this.Service.<foo>不是生命周期钩子中的函数

角使用Karma与茉莉花TypeError: this.Service.<foo>不是生命周期钩子中的函数
EN

Stack Overflow用户
提问于 2021-08-25 08:00:10
回答 2查看 1.3K关注 0票数 2

使用npm run test -- --no-watch --no-progress-command的Karma/Jasmine抛出以下错误:

代码语言:javascript
复制
Chrome 92.0.4515.159 (Mac OS 10.15.7) LoginComponent should create FAILED
    TypeError: this.loggerService.onDebug is not a function
        at LoginComponent.ngAfterViewInit (src/app/pages/login/login.component.ts:22:24)
        at callHook (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:2526:1)
        at callHooks (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:2495:1)
        at executeInitAndCheckHooks (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:2446:1)
        at refreshView (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9516:1)
        at renderComponentOrTemplate (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9559:1)
        at tickRootContext (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10790:1)
        at detectChangesInRootView (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10815:1)
        at RootViewRef.detectChanges (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:22865:1)
        at ComponentFixture._tick (node_modules/@angular/core/__ivy_ngcc__/fesm2015/testing.js:141:1)

你好啊,

我正在用角度12.0.x写一个日志服务。服务连接到ngx-记录器(例如到外部服务器)和存储(Ngx)。

karma.conf.js-File以应用程序的根为目标。

几乎可以直接使用Logger (logging-service.ts):

代码语言:javascript
复制
import { Injectable } from '@angular/core';
import { Store } from '@ngxs/store';
import { NGXLogger } from 'ngx-logger';
import { AddLog, LogEntry } from '../store/log-state';

@Injectable({
  providedIn: 'root',
})
export class LoggerService {
  // This service pipes Log-Messages both to the store as well as to the NGXLogger.
  // Further forwarding by the NGXLogger is dependent on the properties provided in the environment.ts-file.

  constructor(private logger: NGXLogger, private store: Store) {}

  private createLogEntry(level: string, origin: string, msg: string) {
    const dateTime = new Date();
    const log: LogEntry = {
      time: dateTime,
      level: level,
      origin: origin,
      msg: msg,
      noticed: false,
    };
    return log;
  }

  onTrace(origin: string, msg: string) {
    // To NGXLogger
    this.logger.trace(msg);
    // To Store
    this.store.dispatch(new AddLog(this.createLogEntry('trace', origin, msg)));
  }

  onDebug(origin: string, msg: string) {
    // To NGXLogger
    this.logger.trace(msg);
    // To Store
    this.store.dispatch(new AddLog(this.createLogEntry('debug', origin, msg)));
  }

  onInfo(origin: string, msg: string) {
    // To NGXLogger
    this.logger.trace(msg);
    // To Store
    this.store.dispatch(new AddLog(this.createLogEntry('info', origin, msg)));
  }

  ... ... ...
}

从两个不同的位置调用Logger-Service's方法:

  • Login-Component
  • Log-Manager-Component

使用ng serve可以很好地工作。没什么问题。按预期工作。

尽管如此,使用npm run test -- --no-watch --no-progress-command运行Karma/Jasmine仍然会抛出显示在顶部的错误。删除Login-Component中的调用,Karma/Jasmine (=>,它只在Login-Component中)抛出的没有错误。因此,这两个组件导入Logger-Service的方式相同,但只有LoginComponent抛出错误。

区别:Login-Component在角度生命周期钩子中使用‘onInfo’-函数。ngOnInit()和ngAfterViewInit()都提供了相同的结果- Works (ng服务),但没有通过Karma/Jasmine。

我需要生命周期挂钩,因为我想跟踪访问的页面(在基本场景中)。

为了记录这两个受影响的文件:

  • login.component.ts

代码语言:javascript
复制
import { Component, AfterViewInit } from '@angular/core';
import { LoggerService } from 'src/app/services/logging.service';

@Component({
  selector: 'lep-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.less'],
})
export class LoginComponent implements AfterViewInit {
  constructor(
    private loggerService: LoggerService,
  ) {}

  ngAfterViewInit() {
    this.loggerService.onDebug('Login', 'SampleMessage');
  }
}

  • login.component.spec.ts

代码语言:javascript
复制
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoggerService } from 'src/app/services/logging.service';

import { LoginComponent } from './login.component';

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [LoginComponent],
      providers: [{ provide: LoggerService, useClass: class {} }],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

来自Log-Manager-Component的那些文件看起来(几乎)是一样的。如前所述,区别是在Log-Manager-Component中行..。

this.loggerService.onDebug('Login','SampleMessage');

。。在由html页面上的按钮触发的函数中。

有什么建议可以解决吗?:)

EN

回答 2

Stack Overflow用户

发布于 2021-08-25 09:39:37

TestBed.configureTestingModule中的测试中,providers: [{ provide: LoggerService, useClass: class {} }]部件意味着应该提供一个空对象(我指的是{}),而不是作为模拟对象提供LoggerService{}空对象没有onDebug函数,这就是在执行测试时抛出this.loggerService.onDebug is not a function错误的原因。(使用ng serve,应用程序可以工作,因为提供了LoggerService本身,它具有onDebug的实现。)

如下所示,如果您想在测试中为LoggerService拥有一个模拟对象,那么所需的函数必须从LoggerService本身进行模拟。例如,如果只需要onDebug函数:

代码语言:javascript
复制
await TestBed.configureTestingModule({
  declarations: [LoginComponent],
  providers: [{ provide: LoggerService, useClass: LoggerServiceMock }],
}).compileComponents();

...

// Outside of the jasmin describes
class LoggerServiceMock {
  onDebug(origin: string, msg: string) {};
}

作为示例,onDebug函数上面是一个空函数,这个空函数将在测试中调用,而不是在LoggerServiceonDebug函数中调用。如果LoggerService本身是在测试中提供的,并且所需的函数是用jamsine间谍过度定义的,那么这种模拟对象的使用可能是不必要的。

票数 2
EN

Stack Overflow用户

发布于 2021-08-25 09:38:33

您的规范可能会失败,因为您正在使用一个空类作为模拟:

providers: [{ provide: LoggerService, useClass: class {} }]

因此,onDebug不是函数抛出的错误。

解决方案1 useValue

我建议传递一个模拟值(useValue:),其中包含一个onDebug函数:

providers: [{ provide: LoggerService, useValue: { onDebug: (origin: string, msg: string) => undefined} }]

解决方案2 useClass

您还可以提供一个简单的模拟类。

在你的文件中:

代码语言:javascript
复制
class LoggerServiceMock {
    onDebug(origin: string, msg: string) { // we do nothing here }
}
...
...
providers: [{ provide: LoggerService, useClass: LoggerServiceMock }]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68919021

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档