Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
AngularCli-在测试期间,未在onSubmit内部执行Subscribe_Angular_Angular Cli_Karma Jasmine - Fatal编程技术网

AngularCli-在测试期间,未在onSubmit内部执行Subscribe

AngularCli-在测试期间,未在onSubmit内部执行Subscribe,angular,angular-cli,karma-jasmine,Angular,Angular Cli,Karma Jasmine,我正在测试一个基本上有电子邮件和密码字段的组件。填写这两个字段后,用户可以单击按钮并向服务器发送请求。当我通过浏览器测试这个组件时,它会执行我想要的行为。但是当我使用spec文件测试组件时,subscribe方法永远不会执行(obs:我在模拟服务)。以下是组件的onSubmit方法: onSubmit(形式验证:NgForm){ if(this.credential.email==未定义| | this.credential.password==未定义){ this.error=“预先设置电子邮

我正在测试一个基本上有电子邮件和密码字段的组件。填写这两个字段后,用户可以单击按钮并向服务器发送请求。当我通过浏览器测试这个组件时,它会执行我想要的行为。但是当我使用spec文件测试组件时,
subscribe
方法永远不会执行(obs:我在模拟服务)。以下是组件的
onSubmit
方法:

onSubmit(形式验证:NgForm){
if(this.credential.email==未定义| | this.credential.password==未定义){
this.error=“预先设置电子邮件地址”
回来
}否则{
this.tokenManagerService.generateNewToken(this.credential);
this.tokenManagerService.retrieveToken().subscribe(令牌=>{
console.log(令牌);
const tokenRetrieved=JSON.parse(令牌);
if(已检索令牌。错误){
this.error=tokenRetrieved.error;
}否则{
foo();
}
});
formAuthentication.resetForm();
}
}
这是规范文件和测试本身的配置:

description('AuthenticationComponent',()=>{
let组件:AuthenticationComponent;
let夹具:组件夹具;
让inputEmail:HTMLInputElement;
让输入密码:HTMLInputElement;
let login按钮:HTMLInputElement;
让tokenManagerServiceMock:tokenManagerServiceMock;
让模拟路由器={
导航:jasmine.createSpy('navigate')
}
在每个之前(()=>{
tokenManagerServiceMock=新的tokenManagerServiceMock();
TestBed.configureTestingModule({
声明:[AuthenticationComponent],
导入:[FormsModule、HttpModule、RouterTestingModule.withRoutes([])],
供应商:[
{提供:TokenManagerService,useValue:tokenManagerServiceMock}
]
});
TestBed.overrideComponent(AuthenticationComponent{
设置:{
供应商:[
{提供:TokenManagerService,useValue:tokenManagerServiceMock}
]
}
});
fixture=TestBed.createComponent(AuthenticationComponent)
fixture.componentInstance.ngOnInit();
tokenManagerServiceMock=TestBed.get(TokenManagerService);
fixture.detectChanges();
inputEmail=fixture.debugElement.nativeElement.querySelector('input[type=text]);
inputPassword=fixture.debugElement.nativeElement.querySelector('input[type=password]');
loginButton=fixture.nativeElement.querySelector('input[type=submit]');
});
它('应该检测到白色字段消息',()=>{
fixture.whenStable()然后(()=>{
inputEmail.value=faker.internet.email();
inputEmail.dispatchEvent(新事件('input'));
inputPassword.value=faker.internet.password();
inputPassword.dispatchEvent(新事件('input'));
loginButton.click();
fixture.detectChanges();
});
});
});
我可能做错了什么

EDIT 1:我很确定
subscribe
方法永远不会执行,因为在subscribe方法中,如果有一个名为
token.error
的节点,组件应该设置一个错误变量以显示在此块中:

<div class="error-block" *ngIf="error">
  <h6>{{ error }}</h6>
</div>

{{error}}
但这个信息从未出现在业力中

编辑2: 这是模拟原始身份验证服务的mockService:

import { Injectable }  from '@angular/core';
import { Credential } from '../models/credential';
import { AuthenticationService } from './authentication.service'
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import * as token from 'rand-token';

@Injectable()
export class TokenManagerServiceMock {

  private tokenKey: string = 'codeToken';
  private subject = new Subject<any>();

  constructor() {}

  public generateNewToken(credential: Credential): void {
    let currentTime:number = (new Date()).getTime();
    if (credential.email == 'eminetto@coderockr.com') {
      const data = token.suid(24);
      this.subject.next(JSON.stringify({ttl: currentTime, data}));
    } else {
      const error = 'Usuário ou senha inválidos';
      this.subject.next(JSON.stringify({ttl: currentTime, error}));
    }
  }

  public retrieveToken(): Observable<string> {
    console.log('achieved retrieve');
    return this.subject.asObservable();
  }
}
从'@angular/core'导入{Injectable};
从“../models/Credential”导入{Credential};
从“./authentication.service”导入{AuthenticationService}
从“rxjs/Observable”导入{Observable};
从'rxjs/Subject'导入{Subject};
从“兰德代币”导入*作为代币;
@可注射()
导出类TokenManagerServiceMock{
私有令牌密钥:字符串='codeToken';
私有主体=新主体();
构造函数(){}
public generateNewToken(凭证:凭证):无效{
让currentTime:number=(新日期()).getTime();
如果(credential.email=='eminetto@coderockr.com') {
const data=token.suid(24);
next(JSON.stringify({ttl:currentTime,data}));
}否则{
常量错误='Usuário ou senha inválidos';
this.subject.next(JSON.stringify({ttl:currentTime,error}));
}
}
public retrieveToken():可观察{
log('retrieve');
返回此.subject.asObservable();
}
}

测试中出现问题的根本原因是模拟类中的主题是使用rxjs
subject
类设置的。您使用的用法表明您应该实际使用
BehaviorSubject
类,以便任何延迟订阅主题的用户(在将值推送到主题上后订阅)在订阅时都可以获得最新的值

通过了解模拟服务中发生的情况,我们可以看到我们有一个延迟订户:

generateNewToken(凭证:凭证):无效{
...
这个。主题。下一个(…);
...
}
retrieveToken():可观察{
返回此.subject.asObservable();
}
您可以在下面的模拟使用中看到这种行为:

this.tokenManagerService.generateNewToken(this.credential);
this.tokenManagerService.retrieveToken().subscribe(…);

首先,我们生成一个新的令牌并将其推送到主题上,返回到组件,最后订阅主题。通过切换到
行为主体
,我们将不会遇到延迟订户看不到从呼叫中推送的值以生成新令牌的问题。

请提供有关您在测试中调试的内容的详细信息
“应检测白字段消息”
,以便其他人可以尝试提供帮助。(例如,您如何知道它没有执行订阅等)@DanielWStrimpel那里有一个
控制台。log
并且再也没有执行过,请提供详细信息,确切说明