Angular 2:如何在单元测试时模拟ChangeDetectorRef [英] Angular 2: How to mock ChangeDetectorRef while unit testing

查看:445
本文介绍了Angular 2:如何在单元测试时模拟ChangeDetectorRef的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始使用Unit-Testing,我已经能够模拟我自己的服务以及一些Angular和Ionic,但无论我做什么 ChangeDetectorRef 保持不变。

I have just started with Unit-Testing, and I have been able to mock my own services and some of Angular and Ionic as well, but no matter what I do ChangeDetectorRef stays the same.

我的意思是这是什么类型的巫术?

I mean which kind of sorcery is this?

beforeEach(async(() => 
    TestBed.configureTestingModule({
      declarations: [MyComponent],
      providers: [
        Form, DomController, ToastController, AlertController,
        PopoverController,

        {provide: Platform, useClass: PlatformMock},
        {
          provide: NavParams,
          useValue: new NavParams({data: new PageData().Data})
        },
        {provide: ChangeDetectorRef, useClass: ChangeDetectorRefMock}

      ],
      imports: [
        FormsModule,
        ReactiveFormsModule,
        IonicModule
      ],
    })
    .overrideComponent(MyComponent, {
      set: {
        providers: [
          {provide: ChangeDetectorRef, useClass: ChangeDetectorRefMock},
        ],
        viewProviders: [
          {provide: ChangeDetectorRef, useClass: ChangeDetectorRefMock},
        ]
      }
    })
    .compileComponents()
    .then(() => {
      let fixture = TestBed.createComponent(MyComponent);
      let cmp = fixture.debugElement.componentInstance;

      let cdRef = fixture.debugElement.injector.get(ChangeDetectorRef);

      console.log(cdRef); // logs ChangeDetectorRefMock
      console.log(cmp.cdRef); // logs ChangeDetectorRef , why ??
    })
  ));







 it('fails no matter what', async(() => {
    spyOn(cdRef, 'markForCheck');
    spyOn(cmp.cdRef, 'markForCheck');

    cmp.ngOnInit();

    expect(cdRef.markForCheck).toHaveBeenCalled();  // fail, why ??
    expect(cmp.cdRef.markForCheck).toHaveBeenCalled(); // success

    console.log(cdRef); // logs ChangeDetectorRefMock
    console.log(cmp.cdRef); // logs ChangeDetectorRef , why ??
  }));







@Component({
  ...
})
export class MyComponent {
 constructor(private cdRef: ChangeDetectorRef){}

 ngOnInit() {
   // do something
   this.cdRef.markForCheck();
 }
}

我已经尝试了一切, async fakeAsync injector([ChangeDetectorRef],()=> {})

I have tried everything , async, fakeAsync, injector([ChangeDetectorRef], () => {}).

没有任何作用。

推荐答案

如果有人遇到这是一种对我有用的方法:

In case anyone runs into this, this is one way that has worked well for me:

当你在构造函数中注入ChangeDetectorRef实例时:

As you are injecting the ChangeDetectorRef instance in your constructor:

 constructor(private cdRef: ChangeDetectorRef) { }

您将 cdRef 作为组件上的私有属性之一,这意味着您可以监视组件,存根该属性并让它返回您想要的任何内容。此外,您可以根据需要断言其调用和参数。

You have that cdRef as one of the private attributes on the component, which means you can spy on the component, stub that attribute and have it return whatever you want. Also, you can assert its calls and parameters, as needed.

在您的spec文件中,调用您的TestBed而不提供ChangeDetectorRef,因为它不会提供您提供的内容。设置相同beforeEach块的组件,因此它在规范之间重置,因为它在文档中完成这里

In your spec file, call your TestBed without providing the ChangeDetectorRef as it won't provide what you give it. Set the component that same beforeEach block, so it is reset between specs as it is done in the docs here:

component = fixture.componentInstance;

然后在测试中直接监视属性

Then in the tests, spy directly on the attribute

describe('someMethod()', () => {
  it('calls detect changes', () => {
    const spy = spyOn((component as any).cdRef, 'detectChanges');
    component.someMethod();

    expect(spy).toHaveBeenCalled();
  });
});

对于间谍,您可以使用 .and.returnValue()并让它返回您需要的任何内容。

With the spy you can use .and.returnValue() and have it return whatever you need.

请注意(组件为任何)用作 cdRef 是一个私有属性。但私有在实际编译的javascript中不存在,因此可以访问。

Notice that (component as any) is used as cdRef is a private attribute. But private doesn't exist in the actual compiled javascript so it is accessible.

如果你想在运行时以这种方式访问​​测试的私有属性,那取决于你。我个人对它没有任何问题,我按照我的规格来做更多的报道。

It is up to you if you want to access private attributes at runtime that way for your tests. I personally don't have any problem with it, I do it on my specs to get more coverage.

这篇关于Angular 2:如何在单元测试时模拟ChangeDetectorRef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆