Unit testing Angular2&;测试平台:如何模拟AngularFire2/可观察数据服务?

Unit testing Angular2&;测试平台:如何模拟AngularFire2/可观察数据服务?,unit-testing,angular,firebase,angularfire2,testbed,Unit Testing,Angular,Firebase,Angularfire2,Testbed,我真的很难理解测试床是如何工作的,以及如何使用它来模拟数据检索(通过AngularFire2,即观察值)/推进离线单元测试。如果有人能提供一个简单的例子来研究它,事情会变得简单得多 下面是StateService的(部分)。然后,我将此服务注入另一个组件,并打印出GraphModule名称,例如 图形模块.component.html {{module.name}} 图形模块.component.ts @Injectable() export class StateService { gra

我真的很难理解测试床是如何工作的,以及如何使用它来模拟数据检索(通过AngularFire2,即观察值)/推进离线单元测试。如果有人能提供一个简单的例子来研究它,事情会变得简单得多

下面是StateService的(部分)。然后,我将此服务注入另一个组件,并打印出GraphModule名称,例如

图形模块.component.html

{{module.name}}

图形模块.component.ts

@Injectable()
export class StateService {

 graphModules$: FirebaseListObservable<any>;
  private auth;

  constructor(public af: AngularFire) {
    af.auth.subscribe(
      latestAuth => {
        this.graphModules$ = af.database.list('/graphModules', {
          query: {
            orderByChild: 'archived',
            equalTo: false
          }
        });
      },
      errors => {
        this.auth = {uid: 'AUTH PROBLEMS'};
        throw 'Problems authenticating';
      }
    );
  }

  saveToDB(key: string, value: any) { 
     this.af.database.list('/graphModules').update(key, value);
     ...
  }
...
}
class MockStateService {
  public graphModules$: Observable<GraphModule[]>;
  constructor () {
    this.graphModules$ = Observable.of<GraphModule[]>([
      {
        name: 'first',
        ...
      },
      {
        name: 'second',
        ...
      }
    ]);
  }
  updateGraphModule(key: string, value: any) {
    // Not sure what to put here in order to emit new value on graphModules$
  }
}



describe('ModulesComponent', () => {
  let fixture:  ComponentFixture<ModulesComponent>;
  beforeEach(() => {
    this.service = new MockStateService();
    TestBed.configureTestingModule({
      imports: [AppModule],
      providers: [{provide: StateService, useValue: this.service }]
    });
    fixture = TestBed.createComponent(ModulesComponent);
  });

  it('should print out two graphModules', async(() => {
    fixture.whenStable().then(() => {
      fixture.detectChanges();
      const test = fixture.nativeElement.querySelectorAll('.module-card');
      expect(fixture.nativeElement.querySelectorAll('.module-card').length).toBe(2);
    });
  }));


  it('should retrieve new data from observer and update DOM when the first graph-module has been given a new name', async(() => {
    fixture.whenStable().then(() => {
      fixture.detectChanges();
      this.service.updateGraphModule(0, {name: 'new name'});
      // What should I write here to test if the DOM is correctly updated?
    });
  }));
 }));
});
constructor(publicss:StateService){}

state.service.ts

@Injectable()
export class StateService {

 graphModules$: FirebaseListObservable<any>;
  private auth;

  constructor(public af: AngularFire) {
    af.auth.subscribe(
      latestAuth => {
        this.graphModules$ = af.database.list('/graphModules', {
          query: {
            orderByChild: 'archived',
            equalTo: false
          }
        });
      },
      errors => {
        this.auth = {uid: 'AUTH PROBLEMS'};
        throw 'Problems authenticating';
      }
    );
  }

  saveToDB(key: string, value: any) { 
     this.af.database.list('/graphModules').update(key, value);
     ...
  }
...
}
class MockStateService {
  public graphModules$: Observable<GraphModule[]>;
  constructor () {
    this.graphModules$ = Observable.of<GraphModule[]>([
      {
        name: 'first',
        ...
      },
      {
        name: 'second',
        ...
      }
    ]);
  }
  updateGraphModule(key: string, value: any) {
    // Not sure what to put here in order to emit new value on graphModules$
  }
}



describe('ModulesComponent', () => {
  let fixture:  ComponentFixture<ModulesComponent>;
  beforeEach(() => {
    this.service = new MockStateService();
    TestBed.configureTestingModule({
      imports: [AppModule],
      providers: [{provide: StateService, useValue: this.service }]
    });
    fixture = TestBed.createComponent(ModulesComponent);
  });

  it('should print out two graphModules', async(() => {
    fixture.whenStable().then(() => {
      fixture.detectChanges();
      const test = fixture.nativeElement.querySelectorAll('.module-card');
      expect(fixture.nativeElement.querySelectorAll('.module-card').length).toBe(2);
    });
  }));


  it('should retrieve new data from observer and update DOM when the first graph-module has been given a new name', async(() => {
    fixture.whenStable().then(() => {
      fixture.detectChanges();
      this.service.updateGraphModule(0, {name: 'new name'});
      // What should I write here to test if the DOM is correctly updated?
    });
  }));
 }));
});
@Injectable()
导出类状态服务{
graphModules$:FirebaseListObservable;
私人授权;
建造商(公共af:AngularFire){
af.auth.subscribe(
latestAuth=>{
this.graphModules$=af.database.list(“/graphModules”{
查询:{
orderByChild:“已存档”,
埃奎尔托:错
}
});
},
错误=>{
this.auth={uid:'auth PROBLEMS'};
抛出“认证问题”;
}
);
}
saveToDB(键:字符串,值:任意){
this.af.database.list('/graphModules').update(key,value);
...
}
...
}
我想测试的是

1) 给定“graphModules”的模拟/存根,正确数量的.card模块将打印到DOM

2) 使用s.saveToDB()更新其中一个模块后,将在DOM中更新名称

另一方面,如果您对我的数据检索“体系结构”有其他意见,也非常欢迎:)

非常感谢

编辑:

好的,我发现了如何修复1号。考试通过了。问题2尚待回答。等级库文件现在如下所示:

图形模块.component.spec.ts

@Injectable()
export class StateService {

 graphModules$: FirebaseListObservable<any>;
  private auth;

  constructor(public af: AngularFire) {
    af.auth.subscribe(
      latestAuth => {
        this.graphModules$ = af.database.list('/graphModules', {
          query: {
            orderByChild: 'archived',
            equalTo: false
          }
        });
      },
      errors => {
        this.auth = {uid: 'AUTH PROBLEMS'};
        throw 'Problems authenticating';
      }
    );
  }

  saveToDB(key: string, value: any) { 
     this.af.database.list('/graphModules').update(key, value);
     ...
  }
...
}
class MockStateService {
  public graphModules$: Observable<GraphModule[]>;
  constructor () {
    this.graphModules$ = Observable.of<GraphModule[]>([
      {
        name: 'first',
        ...
      },
      {
        name: 'second',
        ...
      }
    ]);
  }
  updateGraphModule(key: string, value: any) {
    // Not sure what to put here in order to emit new value on graphModules$
  }
}



describe('ModulesComponent', () => {
  let fixture:  ComponentFixture<ModulesComponent>;
  beforeEach(() => {
    this.service = new MockStateService();
    TestBed.configureTestingModule({
      imports: [AppModule],
      providers: [{provide: StateService, useValue: this.service }]
    });
    fixture = TestBed.createComponent(ModulesComponent);
  });

  it('should print out two graphModules', async(() => {
    fixture.whenStable().then(() => {
      fixture.detectChanges();
      const test = fixture.nativeElement.querySelectorAll('.module-card');
      expect(fixture.nativeElement.querySelectorAll('.module-card').length).toBe(2);
    });
  }));


  it('should retrieve new data from observer and update DOM when the first graph-module has been given a new name', async(() => {
    fixture.whenStable().then(() => {
      fixture.detectChanges();
      this.service.updateGraphModule(0, {name: 'new name'});
      // What should I write here to test if the DOM is correctly updated?
    });
  }));
 }));
});
class-MockStateService{
公共图形模块$:可见;
构造函数(){
此.graphModules$=可观察的.of([
{
姓名:'第一',
...
},
{
姓名:'第二',
...
}
]);
}
updateGraphModule(键:字符串,值:任意){
//不确定要在此处放置什么才能在graphModules上发出新值$
}
}
描述('ModuleComponent',()=>{
let夹具:组件夹具;
在每个之前(()=>{
this.service=new MockStateService();
TestBed.configureTestingModule({
导入:[AppModule],
提供程序:[{provide:StateService,useValue:this.service}]
});
fixture=TestBed.createComponent(模块组件);
});
它('应该打印两个图形模块',异步(()=>{
fixture.whenStable()然后(()=>{
fixture.detectChanges();
常量测试=fixture.nativeElement.querySelectorAll(“.module card”);
expect(fixture.nativeElement.querySelectorAll(“.module card”).length.toBe(2);
});
}));
它('当第一个图形模块被赋予新名称时,应该从观察者检索新数据并更新DOM',异步(()=>{
fixture.whenStable()然后(()=>{
fixture.detectChanges();
this.service.updateGraphModule(0,{name:'new name'});
//我应该在这里写些什么来测试DOM是否正确更新?
});
}));
}));
});

这方面运气好吗?