【问题标题】:Expected spy navigate to have been called with [ [ '/ProjectData/MasterSequence' ] ] but it was never called预期的间谍导航已使用 [ [ '/ProjectData/MasterSequence' ] ] 调用,但从未调用过
【发布时间】:2019-12-04 16:07:22
【问题描述】:

我正在为 Angular7 模板中的函数编写单元测试用例。它是一个登录组件,登录功能在 http 请求中具有 router.navigate,以在正确登录时路由到仪表板。 但我收到错误 -

错误:使用 [ [ '/ProjectData/MasterSequence' ] ] 调用了预期的间谍导航,但从未调用过它。 在堆栈 (http://localhost:9876/absolute/home/hp/Downloads/ICICI/ICICI_UI/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2455:17) 在 buildExpectationResult (http://localhost:9876/absolute/home/hp/Downloads/ICICI/ICICI_UI/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2425:14) 在 Spec.expectationResultFactory (http://localhost:9876/absolute/home/hp/Downloads/ICICI/ICICI_UI/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:901:18) 在 Spec.addExpectationResult (http://localhost:9876/absolute/home/hp/Downloads/ICICI/ICICI_UI/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:524:34) 在 Expectation.addExpectationResult (http://localhost:9876/absolute/home/hp/Downloads/ICICI/ICICI_UI/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:845:21) 在 Expectation.toHaveBeenCalledWith (http://localhost:9876/absolute/home/hp/Downloads/ICICI/ICICI_UI/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2369:12) 在用户上下文。 (http://localhost:9876/src/app/authentication/login2/login2.component.spec.ts?:208:38)

app.component.html

loginData(value) {
    this.username = value.username;
    this.password = value.password;
    this.dataObj = {
      'username': this.username,
      'password': this.password
    }
    this.loginService.login(this.dataObj).then((data) => {
      console.log("data", data);
      this.response = data;
      console.log("message", this.response.message);
      if (this.response.message == "Login Successful.") {
        this.router.navigate(['/ProjectData/MasterSequence'])
      }
      else {
        this.toastr.error("UserName or Password is incorrect");
      }
    })

app.component.spec.ts

describe('Login2Component', () => {
    let comp: Login2Component;
    let fixture: ComponentFixture<Login2Component>;
    let de: DebugElement;
    let el: HTMLElement;
    beforeEach(async(() => {
        mockRouter = { navigate: jasmine.createSpy('navigate') };
        TestBed.configureTestingModule({
            declarations: [Login2Component, MasterSequenceComponent],

            imports: [
                BrowserModule,
                FormsModule,
                RouterModule,
                ReactiveFormsModule,
                RouterTestingModule,
                HttpClientModule,

                [
                    RouterTestingModule.withRoutes([
                        { path: '/ProjectData/MasterSequence', 
                          component: MasterSequenceComponent }
                    ])
                ]
            ],
            schemas: [CUSTOM_ELEMENTS_SCHEMA],

            providers: [{ provide: ToastrService, useValue: ToastrService }, Login2Service]
        })
            .compileComponents()
            .then(() => {
                //Login2Component
                fixture = TestBed.createComponent(Login2Component);

                comp = fixture.componentInstance;

                de = fixture.debugElement.query(By.css('form'));
                el = de.nativeElement;
            });
    }));

    it('should redirect the user to "login form" component when button is clicked', () => {
        const router = TestBed.get(Router);
        const spy = spyOn(router, 'navigate');
        fixture.detectChanges();

        const button = fixture.debugElement.query(By.css('form[id=loginform]'));

        button.triggerEventHandler('click', null);

        let userN = comp.addLoginData.controls['username'];
        userN.setValue('pallavi');
        let pass = comp.addLoginData.controls['password'];
        pass.setValue(1234);

        let value = {
            username: userN,
            password: pass
        };

        comp.loginData(value);

        expect(spy).toHaveBeenCalledWith(['/ProjectData/MasterSequence']);
    });
});

参考 -

Angular 2/4/6/7 - Unit Testing with Router

使用此代码时的进一步错误 -

it('should redirect the user to "login form" component when button is clicked', () => {
    let value = {
         username: 'user123',
         password: 'pwd'
     };
     comp.username = '';
     comp.password = '';

     spyOn(comp.LoginService,'login').and.callThrough();

    comp.loginData(value);
     expect(comp.username).toBe('user123');
     expect(comp.password).toBe('pwd');
     expect(comp.LoginService.login).toHaveBeenCalledWith(value)

//expect(RouterMock.navigate).toHaveBeenCalledWith(['/ProjectData/MasterSe//quence']);
    });

错误:'未处理的承诺拒绝:',HttpErrorResponse{headers:HttpHeaders{normalizedNames:Map{},lazyUpdate:null,他 aders: Map{}}, status: 0, statusText: 'Unknown Error', url: 'http://192.168.5.128:3002/api/user/login', ok: false, name: 'HttpErrorResponse', message: 'http://192.168.5.128:3002/api/user/login的Http失败响应: 0 Unknown Error ', 错误: ProgressEvent{isTrusted: true}}, ';区域:','ProxyZone',';任务:', 'Promise.then', '; Value:', HttpErrorResponse{headers: HttpHeaders{normalizedNames: Map{}, lazyUpdate: null, headers: Map{}}, status: 0, statusText: 'Unknown Error', url: 'http://192.168.5.128:3002/api/user/login', ok: false,名称:'HttpErrorResponse',消息:'http://192.168.5.128:3002/api/user/login 的 Http 失败响应:0 未知错误',错误:ProgressEvent{isTrusted: true}},未定义

【问题讨论】:

  • 能否请您提供与该测试相关的组件和模板,否则很难弄清楚为什么您的测试无法按预期工作。
  • 好的。谢谢。我会这样做的
  • 好吧,没有看到 html,我真的不明白为什么你会触发按钮点击。您可能需要等待异步作业完成,但这只是猜测。但是一个问题肯定是你需要等到从 loginService 返回的承诺真正解决。在您期望您的间谍已被调用之前,您可以在测试块 it 和 tick() 中使用 fakeAsync。但是,仅此一项是否可以解决您的测试,我无法确定没有看过模板。除了你使用真正的Login2Service的原因是什么?
  • @Techdive 对我在聊天中提供的建议有何更新?

标签: angular typescript unit-testing jasmine karma-jasmine


【解决方案1】:

我找不到loginService.login() 的代码,但我确信它必须进行一些API 调用,因此创建stub 是一个好习惯。类似:

export class LoginServiceStub{
  login(obj){
     return new Promise((resolve, reject) => {
         resolve("whatever_data_is_expected");
     });
   }
}

在spec 文件中:

describe('Login2Component', () => {
  let RouterMock = {
    navigate: jasmine.createSpy('navigate')
  };

 beforeEach(async(() => {
        mockRouter  = { navigate: jasmine.createSpy('navigate') };
        TestBed.configureTestingModule({
        decleration: [ .... ],
        providers: [
             {provide: ToastrService, useValue: ToastrService }, // I am not sure why you have done "useValue" with same Service
             {provide: Login2Service, useClass: Login2ServiceStub },
             {provide: Router, useValue: RouterMock  }
             ], 
      // ... and other deceleration of Test Bed
  )};

})

然后在it 块中:

it('should redirect the user to "login form" component when button is clicked', () => {
       let value = {
            username: 'user123',
            password: 'pwd';
        };
        comp.username = '';
        comp.password = '';
        spyOn(comp.loginService,'login').and.callThrough();
        comp.loginData(value);
        expect(comp.username).toBe('user123');
        expect(comp.password).toBe('pwd');
        expect(comp.loginService.login).toHaveBeenCalledWith(value)
        expect(RouterMock.navigate).toHaveBeenCalledWith(['/ProjectData/MasterSequence']);
    });
});

我也建议你read this collection of articles specifically written for Unit testing in Angular。您可以找到几个链接,这些链接几乎涵盖了所有基本测试场景。

【讨论】:

  • 嗨,Shashank,感谢您的回复。但我收到错误 - 类型“LoginComponent”上不存在属性“LoginService”。我猜...它无法识别 LoginService 或 loginService
  • @Techdive : 你能在构造函数constructor ( public LoginService ) 等中检查它是否公开
  • 纠正后,我仍然收到错误 - 预期的间谍导航已被 [ [ '/ProjectData/MasterSequence' ] ] 调用,但从未调用过。
  • @ Shashank,如果我删除最后一行 - 我得到错误 - 错误:'未处理的承诺拒绝:',HttpErrorResponse{headers:HttpHeaders{normalizedNames:Map{},lazyUpdate:null,标题:Map {}},状态:0,statusText:'未知错误',url:'192.168.5.128:3002/api/user/login',ok:false,名称:'HttpErrorResponse',消息:'192.168.5.128:3002/api/user/login 的 Http 失败响应:0 未知错误',。 ..
  • ....错误:ProgressEvent{isTrusted: true}}, ';区域:','ProxyZone',';任务:', 'Promise.then', '; Value:', HttpErrorResponse{headers: HttpHeaders{normalizedNames: Map{}, lazyUpdate: null, headers: Map{}}, status: 0, statusText: 'Unknown Error', url: '192.168.5.128:3002/api/user/login', ok: false,名称:'HttpErrorResponse',消息:'192.168.5.128:3002/api/user/login 的 Http 失败响应:0 未知错误',错误:ProgressEvent{isTrusted: true}},未定义
猜你喜欢
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-02
  • 2023-03-24
  • 2017-11-18
  • 1970-01-01
  • 2019-02-05
相关资源
最近更新 更多