Typescript 在茉莉花中使用2种不同的模拟进行测试

Typescript 在茉莉花中使用2种不同的模拟进行测试,typescript,testing,mocking,jasmine,karma-jasmine,Typescript,Testing,Mocking,Jasmine,Karma Jasmine,我有这样一个ts守卫: @Injectable({ providedIn: 'root' }) export class AppEssentialsGuard implements CanActivate { private readonly DEFAULT_APP_ID = 'def'; constructor(private appsService: AppsService) {} canActivate(next: ActivatedRouteSnapshot, s

我有这样一个ts守卫:

@Injectable({
  providedIn: 'root'
})

export class AppEssentialsGuard implements CanActivate {

  private readonly DEFAULT_APP_ID = 'def';

  constructor(private appsService: AppsService) {}

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    const url = this.getDefaultAppUrl();
    if (url) {
      window.open(url);
    }
    return false;
  }

  private getDefaultAppUrl(): string {
    const myApp = this.appsService.getAllApps()
      .find(app => app.appId === this.DEFAULT_APP_ID);
    return myApp ? myApp.url : null;
  }
}
我正在为它编写测试,如下所示:

describe('AppEssentialsGuard', () => {
  let guard: AppEssentialsGuard;
  let appsService: AppsService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        mockProvider(RequesterService),
        {provide: AppsService, useClass: AppsServiceMock}
      ]
    });
    appsService = TestBed.inject(AppsService);
    guard = TestBed.inject(AppEssentialsGuard);
  });

  it('should be created', () => {
    expect(guard).toBeTruthy();
  });

  it( 'should open new default app window', () => {
    spyOn(window, 'open');
    let returnValue = guard.canActivate(null, null);
    expect( window.open ).toHaveBeenCalledWith("https://appstore.com/");
    expect(returnValue).toBeFalsy();
  });


});
现在,对于happy flow测试,我正在使用useClass中指定的AppsServiceMock,它返回一个虚拟应用数组,包括一个ID为“def”的应用,以便测试通过

我的问题是,我还想测试这个url返回一个空数组的情况,或者一个没有“def”应用程序的情况,我如何测试这两种情况?我不知道如何使用另一个模拟

我不认识茉莉花


谢谢

您可以通过监视
getAllApps
并在做出断言之前返回值来实现所需的行为。监视并返回值会忽略原始详细信息实现,并始终返回您指定的值

// happy path;
it( 'should open new default app window', () => {
    spyOn(appService, 'getAllApps').and.returnValue([/* add an array of elements you would like */]);
    spyOn(window, 'open');
    let returnValue = guard.canActivate(null, null);
    expect( window.open ).toHaveBeenCalledWith("https://appstore.com/");
    expect(returnValue).toBeFalsy();
  });
// empty array path
it( 'should not open new default app window', () => {
    spyOn(appService, 'getAllApps').and.returnValue([]);
    spyOn(window, 'open');
    let returnValue = guard.canActivate(null, null);
    expect( window.open ).not.toHaveBeenCalled(); // change your assertion here
    expect(returnValue).toBeFalsy();
  });

这不起作用,spyOn没有覆盖原始值@alif50wird,我觉得我提供的应该可以工作。我意识到我在测试的函数中有delay(),这可能会影响它的工作方式吗@我认为你的问题没有延迟,但如果你在不同的情况下有延迟,是的,可能会延迟。我会使用
fakeAsync
tick
进行
延迟
。测试异步和时间可能很困难。