简体   繁体   English

使用ngrx效果Angular5进行茉莉花登录测试

[英]jasmine login test using ngrx effect Angular5

I'm testing a login effects service using jasmine with marbles 我正在使用茉莉花和大理石测试登录效果服务

It's fairly, straightforward; 这是相当直接的。 the user sends login info (email and password) via the store payload to the effect 用户通过商店有效负载发送登录信息(电子邮件和密码)到效果

the api endpoint which check credentials, responds with a token that is decoded to be used as a constructor parameter for the LoginSuccess class, within the effects service. api端点,用于检查凭据,并使用一个令牌进行响应,该令牌经过解码以用作effects服务中LoginSuccess类的构造函数参数。

I've gotten it working, however, I'm finding that the test reaches out to the "real" effects service and returns an object "userState". 我已经开始使用它了,但是,我发现测试到达了“真实”效果服务并返回了一个对象“ userState”。

This object I am mocking in the test also (along with using createSpyObj for the authService, which works) 这个对象,我在测试中还嘲讽(连同使用createSpyObj的authService,它的工作原理)

If the objects don't match (including having matching tokens, which I had to copy from a real login) the test fails, I'm a little lost on this one if someone could give some pointers 如果对象不匹配(包括具有匹配的令牌,我必须从真实登录名中复制这些对象),则测试失败,如果有人可以提供一些指针,我对此会有些迷失

The effects file: 效果文件:

export class LoginEffects {
  constructor(private actions$: Actions,
              private authService: AuthService,
              private router: Router) {}

@Effect() login$: Observable<any> = this.actions$
    .pipe(
      ofType<LogIn>(LOGIN),
      mergeMap(action => {
      return this.authService.login(action.payload.email, action.payload.password)
      .pipe(
        map((data)=> {
           //Decode the returned jwt
          let decodedData = jwt_decode(data.token);
          //userState is being mocked in test as well
          let userState:loginReducer.State = {
            isAuthenticated: true,
            token:data.token,
            name:decodedData.name
          }
          console.log(userState)
         return new LoginSuccess(userState)
        }),
        catchError((error) => {
            return Observable.of(new LogInFailure({ error: error }));
          })
      )
    }),

  )
}

test file: 测试文件:

import { LoginEffects } from "./login.effects";
import { TestBed, fakeAsync } from "@angular/core/testing";
import { provideMockActions } from '@ngrx/effects/testing';
import {of} from 'rxjs/observable/of';
import { cold } from 'jasmine-marbles';
import { AuthService } from "../../../services/auth.service";
import {RouterTestingModule} from "@angular/router/testing";
import { Observable } from "rxjs";
import * as EffectsAction from '../actions/login.actions';
import { StoreModule} from "@ngrx/store";
import { reducers } from "../../../reducers";

describe('LoginEffects', () => {
   let effects, authService;
  let actions$: Observable<any>;
    beforeEach(() => TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        StoreModule.forRoot(reducers, {})
      ],
      providers: [
        LoginEffects,  
        {
          provide: AuthService,
          useValue: jasmine.createSpyObj('authService', ['login'])
        },
        provideMockActions(() => actions$)
      ]
    }));
    beforeEach(() => {
      effects = TestBed.get(LoginEffects);
      authService = TestBed.get(AuthService);
    });

    describe('Effects', () => {
      it('should return response from server', () => {
        // service = TestBed.get(AuthService);
        const payloadInfo = {email: 'test@reflections.co.uk', password:'password'}
        const userState = {
          isAuthenticated: true,
          //copied token     token:'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiTHVrZSIsImlhdCI6MTUzMTQwMTgyOSwiZXhwIjoxNTMxNDAzMDI5LCJzdWIiOiI1OWM3ODA4YzE3Y2UzZTc1ODU4M2RjOWEifQ.Kr6NfLc9mgz8_O6wlnAo1E4jTSE0Q3tB4vqwIQOVWcasSm8MlPPmvx1WqLkRkKx1r_Rba0bjGIQ7iypZNW-XJEqr25GCnL3gparJap5CWqd_4dea48cNbcM_Km5cCkQ746IBVt2uarrqxBMvp4HAp2mP6E-A1XuV04p6VcnincGxwCW5lTQNFySKSVZ-cOOLOdlyhYhsvvPvu-f7J3W0poqniEJICkFaVnweBWogDUonqe_48z_eRauLkIdeLBPj3PO67XVgIGe423P15ZXXmmrXNFT4iGsCSfG_MJdljgTaZl65UcD_bu8wRkYTd4Vh0qBIuULyem4YDolaFMhcKg',
              name:'Luke'
        }
     const action = new EffectsAction.LogIn({type:'LOGIN', payload:payloadInfo});
        const result = new EffectsAction.LoginSuccess(userState)

        actions$ = of(action);
        const response = cold( 'a', {a : userState})
        const expected = cold( 'b', {b : result})
        authService.login.and.returnValue(response);
        console.log(expected)
        expect(effects.login$).toBeObservable(expected);
      });

    });

  });

Basically, it was to do with decoding the response sent from the authService And assigning the data to properties of the userState: 基本上,这与解码从authService发送的响应并将数据分配给userState的属性有关:

  //Decode the returned jwt
     console.log(data)//This would be my mockdetails
      let decodedData = jwt_decode(data.token);
      console.log(decodedData)//This would have the details from logged in user
      let userState:loginReducer.State = {
        isAuthenticated: true,
        token:data.token,
        name:decodedData.name//this is from logged in user throws error
      }
console.log(userState)//This would have the details from logged in user

What this seemed to be doing was; 这似乎是在做; extracting the real logged in user info into memory when decoding and applying to the userState object 解码并应用于userState对象时,将实际登录的用户信息提取到内存中

I saw that I didn't need to decode to get the username I could just grab it from the returned object: 我看到我不需要解码就可以从返回的对象中获取用户名:

map((data)=> {
 let userState:loginReducer.State = {
    isAuthenticated: true,
    token:data.token,
    name:data.name
  }
})

So it works but I couldn't work out what to do if I had to decode? 这样就可以了,但是如果我必须解码,我就无法解决该怎么办?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM