Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 单元测试没有ChangeDetectorRef的提供程序_Unit Testing_Angular_Karma Jasmine_Angular4 - Fatal编程技术网

Unit testing 单元测试没有ChangeDetectorRef的提供程序

Unit testing 单元测试没有ChangeDetectorRef的提供程序,unit-testing,angular,karma-jasmine,angular4,Unit Testing,Angular,Karma Jasmine,Angular4,版本:角4 我将父组件注入子组件中,以通过子组件访问父方法 在父组件中,我必须使用ChangeDetectorRef,因为它有一个将更新运行时的属性 现在代码运行良好,但子组件规范为注入父组件的“ChangeDetectorRef”抛出错误 错误:ChangeDetectorRef没有提供程序 父组件 import { Component, AfterViewChecked, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/

版本:角4

我将父组件注入子组件中,以通过子组件访问父方法

在父组件中,我必须使用ChangeDetectorRef,因为它有一个将更新运行时的属性

现在代码运行良好,但子组件规范为注入父组件的“ChangeDetectorRef”抛出错误

错误:ChangeDetectorRef没有提供程序

父组件

import { Component, AfterViewChecked, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'parent-component',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ParentComponent implements AfterViewChecked {

  stageWidth: number;

  constructor(private ref: ChangeDetectorRef) {
    this.ref = ref;
  }

  //call this function as many times as number of child components within parent-component.
  parentMethod(childInterface: ChildInterface) {
    this.childInterfaces.push(childInterface);
  }

  ngAfterViewChecked() {
    this.elementWidth = this.updateElementWidthRuntime();
    this.ref.detectChanges();
  }
}
import { Component, AfterViewInit } from '@angular/core';
import { ParentComponent } from '../carousel.component';

@Component({
  selector: 'child-component',
  templateUrl: './carousel-slide.component.html',
  styleUrls: ['./carousel-slide.component.scss'],
})
export class ChildComponent implements AfterViewInit {

  constructor(private parentComponent: ParentComponent) {
  }

  ngAfterViewInit() {
    this.parentComponent.parentMethod(this);
  }
}
子组件

import { Component, AfterViewChecked, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'parent-component',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ParentComponent implements AfterViewChecked {

  stageWidth: number;

  constructor(private ref: ChangeDetectorRef) {
    this.ref = ref;
  }

  //call this function as many times as number of child components within parent-component.
  parentMethod(childInterface: ChildInterface) {
    this.childInterfaces.push(childInterface);
  }

  ngAfterViewChecked() {
    this.elementWidth = this.updateElementWidthRuntime();
    this.ref.detectChanges();
  }
}
import { Component, AfterViewInit } from '@angular/core';
import { ParentComponent } from '../carousel.component';

@Component({
  selector: 'child-component',
  templateUrl: './carousel-slide.component.html',
  styleUrls: ['./carousel-slide.component.scss'],
})
export class ChildComponent implements AfterViewInit {

  constructor(private parentComponent: ParentComponent) {
  }

  ngAfterViewInit() {
    this.parentComponent.parentMethod(this);
  }
}
app.html

<parent-component>
    <child-component>
      <div class="box">Content of any height and width</div>
    </child-component>
    <child-component>
      <div class="box">Content of any height and width</div>
    </child-component>
    <child-component>
      <div class="box">Content of any height and width</div>
    </child-component>
</parent-component>

任何高度和宽度的内容
任何高度和宽度的内容
任何高度和宽度的内容
子组件的单元测试

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { ParentComponent } from '../parent.component';
import { ChildComponent } from './child.component';

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ChildComponent],
      providers: [ParentComponent]
    })
      .compileComponents();
  }));

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

  it('should create \'ChildComponent\'', () => {
    expect(component).toBeTruthy();
  });
});
从'@angular/core/testing'导入{async,ComponentFixture,TestBed};
从“../parent.component”导入{ParentComponent};
从“./child.component”导入{ChildComponent};
描述('ChildComponent',()=>{
let组件:ChildComponent;
let夹具:组件夹具;
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[ChildComponent],
提供者:[父组件]
})
.compileComponents();
}));
在每个之前(()=>{
fixture=TestBed.createComponent(ChildComponent);
组件=fixture.componentInstance;
fixture.detectChanges();
});
它('应该创建'ChildComponent\'',()=>{
expect(component.toBeTruthy();
});
});
当我试图在子规范的提供者中添加ChangeDetectorRef时,我得到了以下错误

失败:遇到未定义的提供程序!通常这意味着你有一个 循环依赖关系(可能是由于使用'barrel'index.ts引起的 文件。)


在谷歌搜索和尝试了很多东西后,我找不到解决办法。非常感谢您的帮助。

您正在使用组件作为提供者,这可能不是您的意图。更改测试模块以声明父组件和子组件

TestBed.configureTestingModule({
  declarations: [ChildComponent, ParentComponent],
  providers: []  
})

我可以通过在父组件中将“ChangeDetectorRef”设置为可选的依赖项来消除此错误

constructor(@Optional() private ref: ChangeDetectorRef) {
    this.ref = ref;
}

这样,我的子组件的configureTestingModule将忽略ParentComponent provider。

您是在创建循环依赖项还是“桶”索引。ts?@Tatsuyuki Ishi否我没有使用循环依赖项。就在上面的代码和一些计算。如果我这样做,那么我会得到错误:没有ParentComponent的提供程序!为什么Angular认为ParentComponent需要提供程序?您是否使用@Component装饰器装饰它(ParentComponent)?因为我正在将父组件注入子组件。如果您看到我的子组件,您可以在构造函数中看到它。我这样做的原因是我必须从子组件调用parent方法。到达这里,但尝试声明和提供parentComponent。在这种情况下,您不是在进行单元测试,而是在两个组件之间进行有限的集成测试,因此您可能需要创建具有适当层次结构的测试线束组件。这应该能让依赖注入起作用。我已经做了一天了,你帮了我。谢谢在单元测试或故事书场景中,将其设置为可选是有意义的。