在分层结构中解决角度为4的单元测试用例中的依赖性

时间:2018-03-12 11:24:34

标签: angular karma-jasmine

我是角色的新手,并为我的项目工作单元测试用例。我经历了一些无法解释的Unit Testing

当我尝试为我的项目编写单元测试用例时阅读这些文章后,我无法解决测试用例中的依赖性。由于我有一个分层结构,并且当我在我的测试用例中注入依赖项时,而这些测试用例又调用了其他层,因此依赖关系无法解析。我无法找到如何解决执行测试用例的依赖关系。

我有一个LoginComponent类 一个AuthService类 和一个HttpService类

    import { Component, OnInit } from '@angular/core';
import {Router} from '@angular/router';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
import { HttpService } from '../../common/services/http.service';
import {LocalStorageService} from '../../common/services/local-storage.service';
import { AuthService } from '../../common/services/auth.service';
import {PathConfig} from '../../common/config/path.config';
import { ToastrService } from 'ngx-toastr';

@Component({
  selector: 'app-user-login',
  styleUrls: ['./login.component.scss'],
  templateUrl: './login.component.html'
})
export class LoginComponent implements OnInit {
  public loginForm: FormGroup;
  public submitted: boolean;

  constructor(private router: Router, 
              private httpService: HttpService,
              private localStorageService: LocalStorageService,
              private authService: AuthService,
              private toastr: ToastrService) {}

  ngOnInit () {
    this.loginForm = new FormGroup({
      name: new FormControl('testmarion', [Validators.required]),
      pwd: new FormControl('testmarion', [Validators.required])
    });
  }

  doLogin(value: any, isValid: boolean ) {
    if (isValid) {
      this.authService.login(PathConfig.LOGIN, value)
      .then((data:any)=> {
           this.localStorageService.set("userInfo",JSON.stringify(data.response));
           this.localStorageService.set("AuthToken",data.response.AccessToken);
           this.router.navigate(['/home']);
      }).
      catch(err => {
        this.toastr.error(err.message);
  });

    }
  }
}

    import { Component, OnInit } from '@angular/core';
import {Router} from '@angular/router';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
import { HttpService } from '../../common/services/http.service';
import {LocalStorageService} from '../../common/services/local-storage.service';
import { AuthService } from '../../common/services/auth.service';
import {PathConfig} from '../../common/config/path.config';
import { ToastrService } from 'ngx-toastr';

@Component({
  selector: 'app-user-login',
  styleUrls: ['./login.component.scss'],
  templateUrl: './login.component.html'
})
export class LoginComponent implements OnInit {
  public loginForm: FormGroup;
  public submitted: boolean;

  constructor(private router: Router, 
              private httpService: HttpService,
              private localStorageService: LocalStorageService,
              private authService: AuthService,
              private toastr: ToastrService) {}

  ngOnInit () {
    this.loginForm = new FormGroup({
      name: new FormControl('testmarion', [Validators.required]),
      pwd: new FormControl('testmarion', [Validators.required])
    });
  }

  doLogin(value: any, isValid: boolean ) {
    if (isValid) {
      this.authService.login(PathConfig.LOGIN, value)
      .then((data:any)=> {
           this.localStorageService.set("userInfo",JSON.stringify(data.response));
           this.localStorageService.set("AuthToken",data.response.AccessToken);
           this.router.navigate(['/home']);
      }).
      catch(err => {
        this.toastr.error(err.message);
  });

    }
  }
}

import { Injectable }     from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {LocalStorageService} from "./local-storage.service";
import {ConstantConfig} from "../config/constant.config";
import {HttpHeaders} from "@angular/common/http";

@Injectable()

@Injectable()
export class AuthService {
    constructor ( private http:HttpClient , private localStorage:LocalStorageService) {}
    //Auth REQUEST
    login(url,obj: Object): Promise<any>{
      let body = JSON.stringify(obj); 
       let modifyUrl = url +'?userName='+obj['name']+'&'+'password='+obj['pwd'];
        return this.http.get(modifyUrl)
        .toPromise()
        .then((res:any) => {
          console.log(res);
         return ({'response':res})
        }).catch((error:any) => { return Promise.reject( error || 'Server error')}  )
    }

    //check login status
   isLoggedIn():boolean{
       var data = this.localStorage.get(ConstantConfig.AUTH_TOKEN);
       return data ? true : false ;
   }
}

组件类中的doLogin函数调用AuthService类中的login函数,该函数调用httpservice的get方法来进行api命中。

我正在尝试为doLogin函数创建单元测试用例。 对于这个在login.component.spec.ts文件中我尝试的是通过在构造函数中注入依赖项来创建一个登录组件的实例现在当我在我的单元测试中用我的对象调用doLogin函数时我得到了无法调用Login函数的错误未定义的。同样的情况是我使用TestBed。

我无法弄清楚如何解决服务的依赖关系。

1 个答案:

答案 0 :(得分:0)

你必须嘲笑你的组件。

例如,这就是你嘲笑服务的方式:

const authMock = {
  login: () => Promise.resolve(true),
  isLoggedIn: () => true
};

TestBed.configureTestingModule({
  declarations: [AppComponent],
  providers: [
    { provide: AuthService, useValue: authMock }
  ]
}).compileComponents();

authMock变量中,您需要将每个函数,您服务中的每个变量都放在其中。这样,当您的测试组件调用该服务时,它实际上会调用您的模拟。

然后您可以像这样模拟返回:

it('should call the service if the form is valid', () => {
  spyOn(component['authService'], login).and.returnValue(Promise.resolve({data: 'anything you want there'}));

  component.doLogin('value', true);

  expect(component['authService'].login).toHaveBeenCalledWith(PathConfig.LOGIN, 'value');
});