как отправить сообщение от Наблюдаемого Наблюдателю в модульном тесте - PullRequest
0 голосов
/ 01 января 2019

У меня есть UserManagementService, который выставляет наблюдаемую величину BehaviourSubject.

this.userSignInState $ = this.signInStateSubject.asObservable ();

userSignInState$ публично, а signInStateSubject приватно.

Я подписываюсь на userSignInState$в компоненте nav.

constructor(public userManagementService: UserManagementService, private fb:FormBuilder, private helper:HelperService) {
    this.userSignInStateSubscription = this.userManagementService.userSignInState$.subscribe(
          (result:Result)=> {
            console.log("In nav - result from user signin state ",result);
            let subscribed:UserSigninState = result.additionalInfo;
            console.log("new user signin state received:", subscribed);
            this.userLoggedIn = subscribed.isSignedIn;
            if(subscribed.isSignedIn && subscribed['additional-info'] !== ''){
              this.profile = JSON.parse(subscribed['additional-info']) as UserProfileAPI
            }
            if(!subscribed.isSignedIn && subscribed['additional-info'] !== ''){
            //  let error:ServerResponseAPI = JSON.parse(subscribed['additional-info']) as ServerResponseAPI
              //let errorMessage:string = this.helper.userFriendlyErrorMessage(error);
              this.navEvent.emit(new NavContext(subscribed['additional-info']));
            }
          },
        (error:ServerResponseAPI)=>{
            console.log("got error from the Observable: ",error);

           let errorMessage:string = this.helper.userFriendlyErrorMessage(error);
           this.navEvent.emit(new NavContext(errorMessage));
    //       this.userloggedIn =false;
      },
      ()=>{ //observable complete
        console.log("observable completed")
        //this.userloggedIn =false;
      });
  }

Я хочу провести модульное тестирование nav.Как часть спецификации, я хочу использовать next из signInStateSubject и убедиться, что nav получает сообщение, отправленное в next.Но я не могу этого сделать, поскольку signInStateSubject является приватным.Я мог бы сделать это, если я сделаю signInStateSubject публичным, но это звучит неправильно.

Я написал следующую спецификацию, но она работает, только если я сделаю signInStateSubject общедоступной.

fit('should subscribe to user sign in state observable',()=>{
    let userManagementService = TestBed.get(UserManagementService);
    let navComponent:NavComponentComponent = component;
    console.log('component is ',navComponent);
    navComponent.userLoggedIn = false;
    let dummyUserProfile = new UserProfileAPI(new User('fn','ln','test@test.com'));
    userManagementService.signInStateSubject.next(new Result('success',(new UserSigninState(true,JSON.stringify(dummyUserProfile ))))); //THIS WORKS ONLY IF signInStateSubject IS PUBLIC
    expect(navComponent.userLoggedIn).toBe(true)
  });

1 Ответ

0 голосов
/ 02 января 2019

Поскольку я делаю юнит-тестирование, я должен был высмеять UserManagementService.Сделать это.Я создал фиктивный класс, который содержит методы и свойства UserManagementService, которые nav использует.

class MockUserManagementService {
  signInStateSubject:BehaviorSubject<Result> ;
  userSignInState$:Observable<Result>;//naming convention for Streams has $ in the end.

  constructor(){
    this.signInStateSubject = new BehaviorSubject<Result>(new Result('initial',""));//create Observable. Other components can subscribe to it now to get notifications/values
    this.userSignInState$ = this.signInStateSubject.asObservable();

  }
  getUserProfile(userId: UserID){
    console.log('mocked getUserProfile called');
  }
}

, затем я provide имитируемый класс вместо реального UserManagementClass

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ...],
      imports:[...],
      providers:[...,
        {provide: UserManagementService,useClass:MockUserManagementService},//mock user management service
    })
    .compileComponents();
  }));

Спецификации такие же, как были раньше.Но на этот раз мне не нужно было делать какие-либо свойства реальной UserManagementService общедоступной, так как сервис поиздевался!

it('should subscribe to user sign in state observable',()=>{
    let navComponent:NavComponentComponent = component;
    let userManagementService = TestBed.get(UserManagementService);//component.userManagementService;
    console.log('mock service is ',userManagementService);
    console.log('subject is ',userManagementService.signInStateSubject);
    console.log('observable is ',userManagementService.userSignInState$);
    console.log('nav is ',navComponent);
    expect(navComponent.userSignInStateSubscription.closed).toBe(false);
  });

  it('should should set user as signedIn for successful signin attempt',()=>{
    let navComponent:NavComponentComponent = component;
    /*The idea of unit test is that UserManagementService might not be available yet
    so mock UserManagementService
     */
    let userManagementService = TestBed.get(UserManagementService);//component.userManagementService;
    console.log('got mocked user management service',userManagementService);
    //component.subscribeToUserSignInState();
    console.log('component is ',navComponent);
    navComponent.userLoggedIn = false;
    let dummyUserProfile = new UserProfileAPI(new User('manu','chadha','test@test.com'));
    console.log('dummy profile is ',dummyUserProfile);
    console.log('dummy profile is JSON stringify',JSON.stringify(dummyUserProfile));
    let userSignInState = new UserSigninState(true,JSON.stringify(dummyUserProfile));
    console.log('user signin state ',userSignInState);
    userManagementService.signInStateSubject.next(new Result('success',userSignInState));
    //userManagementService.signInStateSubject.next(new Result('success1',(new UserSigninState(true,JSON.stringify(dummyUserProfile))).toString));
    expect(navComponent.userLoggedIn).toBe(true)
  });

  it('should get user\'s profile',()=>{
    let userManagementService = TestBed.get(UserManagementService);
    let navComponent:NavComponentComponent = component;
    console.log('component is ',navComponent);
    navComponent.profile = new UserProfileAPI(new User("fn","ln","test@test.com"));
    spyOn(userManagementService,'getUserProfile');
    component.onProfileClick();
    let userId = new UserID(navComponent.profile['external-profile'].email);
    expect(userManagementService.getUserProfile).toHaveBeenCalledWith(userId);
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...