【问题标题】:Testing with 2 different mocks in Jasmine在 Jasmine 中使用 2 个不同的模拟进行测试
【发布时间】:2020-09-07 13:59:39
【问题描述】:

我有一个这样的 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();
  });


});

现在对于快乐流测试,我使用在 useClass 中指定的 AppsServiceMock,它返回一组虚拟应用程序,其中包括一个 ID 为“def”的应用程序以通过测试。

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

我是茉莉花的新手

谢谢!

【问题讨论】:

    标签: typescript testing mocking jasmine karma-jasmine


    【解决方案1】:

    您可以通过监视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 不会覆盖原始值@AliF50
    • 奇怪,我觉得我提供的应该可以工作。
    • 我意识到我在被测试的函数中有延迟(),这可能会影响它的工作方式吗? @阿里F50
    • 我没有看到您的问题有延迟,但如果您在其他情况下有它,是的,它可能会。我会使用fakeAsynctick 作为delay。测试异步和时间可能很困难。
    猜你喜欢
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    • 2015-09-18
    • 2013-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多