我已经嘲笑了服务,为什么在不注入服务依赖性的情况下仍然会出错?
I already mocked the service why still get error with not injecting dependency of service?
我正在为我的 Angular 组件编写单元测试,在我称为服务的一个组件中,它帮助在后端注册 reader。在测试中,我模拟了该服务,但每次我仍然因为没有注入原始服务的依赖而出错,为什么?我的理解是,一旦我模拟了服务,我们就不应该考虑这些依赖关系。
错误如下:
Chrome 92.0.4515.159 (Mac OS 10.15.7) RegisterComponent 应该创建失败
NullInjectorError:R3InjectorError(DynamicTestModule)[ReaderAuthService -> HttpClient -> HttpClient]:
NullInjectorError:没有 HttpClient 的提供者!
错误属性:Object({ ngTempTokenPath: null, ngTokenPath: [ 'ReaderAuthService', 'HttpClient', 'HttpClient' ] })
NullInjectorError:R3InjectorError(DynamicTestModule)[ReaderAuthService -> HttpClient -> HttpClient]:
NullInjectorError:没有 HttpClient 的提供者!
在 NullInjector.get (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11100:1)
在 R3Injector.get (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11267:1)
在 R3Injector.get (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11267:1)
以下是我的测试代码:
fdescribe('RegisterComponent', () => {
let regComponent: ReaderRegisterComponent;
let fixture: ComponentFixture<ReaderRegisterComponent>;
let registerSpy: jasmine.Spy;
let router: jasmine.SpyObj<Router>;
beforeEach(async () => {
const authServiceSpy = jasmine.createSpyObj('ReaderAuthService', ['register']);
registerSpy = authServiceSpy.register.and.returnValue(of(readerStub()));
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
const loggerSpy = jasmine.createSpyObj('NGXLogger', ['info', 'warn', 'error']);
await TestBed.configureTestingModule({
providers: [
{
Provide: ReaderAuthService,
useValue: authServiceSpy,
},
{
provide: Router,
useValue: routerSpy,
},
{
provide: NGXLogger,
useValue: loggerSpy,
},
FormBuilder,
],
imports: [
RouterTestingModule,
ReactiveFormsModule,
],
declarations: [ReaderRegisterComponent]
})
.compileComponents();
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
});
beforeEach(() => {
fixture = TestBed.createComponent(ReaderRegisterComponent);
regComponent = fixture.componentInstance;
fixture.detectChanges();
});
fit('should create', () => {
expect(regComponent).toBeTruthy();
});
});
以下是我的组件代码:
@Component({
selector: 'app-reader-register',
templateUrl: './reader-register.component.html',
styleUrls: ['./reader-register.component.css']
})
export class ReaderRegisterComponent implements OnInit {
constructor(
private router: Router,
private fb: FormBuilder,
private readerAuthService: ReaderAuthService,
private logger: NGXLogger,
) { }
registerForm = this.fb.group({
username: ['', [Validators.minLength(3), Validators.pattern('[a-zA-Z0-9_]*')]],
password: ['', Validators.minLength(5)],
confirmPassword: ['', Validators.minLength(5)],
email: ['', Validators.email],
firstName: [''],
lastName: [''],
gender: [''],
birthday: [''],
phoneNumber: [''],
homeAddress: [''],
province: [''],
postcode: [''],
securityQuestion: ['', Validators.required],
securityAnswer: ['', Validators.required],
})
ngOnInit(): void {
// Disable form submissions if there are invalid fields
(function () {
// Fetch all forms we want to apply custom validation styles to
var forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
}
register() {
const val: RegisterReaderDto = this.registerForm.value;
if (val.confirmPassword === val.password) {
this.readerAuthService.register(val).subscribe((data) => {
if (!data) {
window.alert('The username already exist, please choose another one.');
return null;
}
this.logger.info(`User ${data.username} already successfully registered in system.`);
this.router.navigateByUrl('/reader/login');
})
} else {
this.logger.warn('Passwords are not matched, please check')
window.alert('Passwords are not matched, please check')
}
}
}
你打错了,改一下
Provide: ReaderAuthService,
至
provide: ReaderAuthService,
我正在为我的 Angular 组件编写单元测试,在我称为服务的一个组件中,它帮助在后端注册 reader。在测试中,我模拟了该服务,但每次我仍然因为没有注入原始服务的依赖而出错,为什么?我的理解是,一旦我模拟了服务,我们就不应该考虑这些依赖关系。
错误如下: Chrome 92.0.4515.159 (Mac OS 10.15.7) RegisterComponent 应该创建失败 NullInjectorError:R3InjectorError(DynamicTestModule)[ReaderAuthService -> HttpClient -> HttpClient]: NullInjectorError:没有 HttpClient 的提供者! 错误属性:Object({ ngTempTokenPath: null, ngTokenPath: [ 'ReaderAuthService', 'HttpClient', 'HttpClient' ] }) NullInjectorError:R3InjectorError(DynamicTestModule)[ReaderAuthService -> HttpClient -> HttpClient]: NullInjectorError:没有 HttpClient 的提供者! 在 NullInjector.get (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11100:1) 在 R3Injector.get (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11267:1) 在 R3Injector.get (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11267:1)
以下是我的测试代码:
fdescribe('RegisterComponent', () => {
let regComponent: ReaderRegisterComponent;
let fixture: ComponentFixture<ReaderRegisterComponent>;
let registerSpy: jasmine.Spy;
let router: jasmine.SpyObj<Router>;
beforeEach(async () => {
const authServiceSpy = jasmine.createSpyObj('ReaderAuthService', ['register']);
registerSpy = authServiceSpy.register.and.returnValue(of(readerStub()));
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
const loggerSpy = jasmine.createSpyObj('NGXLogger', ['info', 'warn', 'error']);
await TestBed.configureTestingModule({
providers: [
{
Provide: ReaderAuthService,
useValue: authServiceSpy,
},
{
provide: Router,
useValue: routerSpy,
},
{
provide: NGXLogger,
useValue: loggerSpy,
},
FormBuilder,
],
imports: [
RouterTestingModule,
ReactiveFormsModule,
],
declarations: [ReaderRegisterComponent]
})
.compileComponents();
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
});
beforeEach(() => {
fixture = TestBed.createComponent(ReaderRegisterComponent);
regComponent = fixture.componentInstance;
fixture.detectChanges();
});
fit('should create', () => {
expect(regComponent).toBeTruthy();
});
});
以下是我的组件代码:
@Component({
selector: 'app-reader-register',
templateUrl: './reader-register.component.html',
styleUrls: ['./reader-register.component.css']
})
export class ReaderRegisterComponent implements OnInit {
constructor(
private router: Router,
private fb: FormBuilder,
private readerAuthService: ReaderAuthService,
private logger: NGXLogger,
) { }
registerForm = this.fb.group({
username: ['', [Validators.minLength(3), Validators.pattern('[a-zA-Z0-9_]*')]],
password: ['', Validators.minLength(5)],
confirmPassword: ['', Validators.minLength(5)],
email: ['', Validators.email],
firstName: [''],
lastName: [''],
gender: [''],
birthday: [''],
phoneNumber: [''],
homeAddress: [''],
province: [''],
postcode: [''],
securityQuestion: ['', Validators.required],
securityAnswer: ['', Validators.required],
})
ngOnInit(): void {
// Disable form submissions if there are invalid fields
(function () {
// Fetch all forms we want to apply custom validation styles to
var forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
}
register() {
const val: RegisterReaderDto = this.registerForm.value;
if (val.confirmPassword === val.password) {
this.readerAuthService.register(val).subscribe((data) => {
if (!data) {
window.alert('The username already exist, please choose another one.');
return null;
}
this.logger.info(`User ${data.username} already successfully registered in system.`);
this.router.navigateByUrl('/reader/login');
})
} else {
this.logger.warn('Passwords are not matched, please check')
window.alert('Passwords are not matched, please check')
}
}
}
你打错了,改一下
Provide: ReaderAuthService,
至
provide: ReaderAuthService,