gpt4 book ai didi

angular - < spy > : could not find an object to spy upon for login() - Angular TestBed

转载 作者:搜寻专家 更新时间:2023-10-30 21:37:26 24 4
gpt4 key购买 nike

我正在尝试为名为 Login.Component.ts 的组件之一编写单元测试,其代码如下所示。我尝试了各种方法,但无法获得成功的回应。在解释组件和服务代码之前,我想知道——

  1. TestBed – 我的理解是 Angular 中的测试平台启动并设置所有样板代码(需要进行测试,例如创建 View 、初始化和注入(inject)服务、创建路由器,所有这些仅用于测试环境)本身,我们需要做的就是编写一些像下面这样的最小代码——

    beforeEach(() => {
    TestBed.configureTestingModule({
    imports:[RouterTestingModule.withRoutes([])],
    declarations: [LoginComponent],
    providers: [AuthenticationService]
    })
    .compileComponents();


    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    authenticationservice = TestBed.get(AuthenticationService);

    });

但看起来我的理解是错误的,因为组件和身份验证服务看起来不像我收到的错误所显示的对象 –

<spyOn> : could not find an object to spy upon for login() - Angular TestBed

登录.Component.ts -

@Component({
selector: 'app-login',
templateUrl: './login.component.html'
})
export class LoginComponent implements OnInit {

constructor(
private authenticationService: AuthenticationService,
private router: Router
) { }

ngOnInit() {
}

login({ formValue }: { formValue: LoginRequest }) {
this.authenticationService.login(formValue.user, formValue.password)
.subscribe(
res => {
this.router.navigate(['/']);
},
error => {
Console.log(“Login Error”);
});
}
}

Authentication.service.ts

@Injectable()
export class AuthenticationService {

constructor(private httpClient: HttpClient) { }

login(user: string, pass: string): Observable<authToken> {
return this.httpClient.post<authToken >(SomeURI+'/oauth/token', {},
{
params: new HttpParams()
.set('username', userId)
.set('password', password)
}
).do(this.htoken);
}

private htoken(token: authToken) {
//some local storage logic here
}

approutes.module.ts

const appRoutes: Routes = [
30. { path: '', component: HomeComponent, canActivate: [IsAuthenticatedActivateGuard] },

{ path: 'login', component: LoginComponent},

{ path: '**', component: NotFoundComponent, canActivate: [IsAuthenticatedActivateGuard] }
];

@NgModule({
imports: [
RouterModule.forRoot(
appRoutes
)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }

写作测试 -

方法 1 -

//imports

fdescribe('LoginComponent', () => {
let component: LoginComponent;
let authenticationservice: AuthenticationService;
let router: Router;
let spyService: any;
let httpClient: HttpClient;

interface LoginRequest {
user: string;
password: string;
}

let creds: LoginRequest = {
user: "username",
password: "userpasswd"
}

let m: MenuConfig = {
}
let oToken: OauthToken = {
access_token: "abc",
token_type: "jj",
refresh_token: "y",
expires_in: 10,
scope: "g",
acessibleMenuItems: m
};


beforeEach(() => {
component = new LoginComponent(authenticationservice, router, null);
authenticationservice = new AuthenticationService(httpClient);
});


fit('should login successfully', () => {
spyService = spyOn(authenticationservice, 'login').and.callFake(() => {
return Observable.of(oToken);
});
component.login({ value: creds });
expect(spyService).toHaveBeenCalledTimes(1);
})
});

错误 -

TypeError: Cannot read property 'navigate' of undefined

方法 2 – 当我想到使用 TestBed 时假设它会处理所有事情,

//imports

describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let authenticationservice: AuthenticationService;
let router: Router;
let spyService: any;
let spyRouter: any;
let httpClient: HttpClient;

interface LoginRequest {
user: string;
password: string;
}

let creds: LoginRequest = {
user: "username",
password: "userpasswd"
}

let m: MenuConfig = {
}
let oToken: OauthToken = {
access_token: "abc",
token_type: "jj",
refresh_token: "y",
expires_in: 10,
scope: "g",
acessibleMenuItems: m
};

beforeEach(() => {
TestBed.configureTestingModule({
imports:[RouterTestingModule.withRoutes([])],
declarations: [LoginComponent],
providers: [AuthenticationService]
})
.compileComponents();

fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
authenticationservice = TestBed.get(AuthenticationService);

//fixture.detectChanges();
});

it('should login successfully', () => {
spyService = spyOn(authenticationservice, 'login').and.callFake(() => {
return Observable.of(oToken);
});
//spyRouter = spyOn((<any>component).router, 'navigate').and.callThrough();
component.login({ value: creds });
expect(spyService).toHaveBeenCalledTimes(1);
//expect(spyRouter).toHaveBeenCalledTimes(1);
})
});

错误 -

Error: Template parse errors:
'app-messages' is not a known element:
1. If 'app-messages' is an Angular component, then verify that it is part of this module.
2. If 'app-messages' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("<h4>Login</h4>
<hr>
[ERROR ->]<app-messages></app-messages>
<!-- Really good forms resource: https://toddmotto.com/angular-2-forms-"): ng:///DynamicTestModule/LoginComponent.html@2:0
There is no directive with "exportAs" set to "ngForm" ("nputs 'name' attribute -->
<form name="form" class="form-horizontal" novalidateautocomplete="false" [ERROR ->]#f="ngForm" (ngSubmit)="login(f)">
<div class="form-group">
<label for="user-input">User Id</la"): ng:///DynamicTestModule/LoginComponent.html@6:73
There is no directive with "exportAs" set to "ngModel" (" <input class="form-control" type="text" id="user-input" placeholder="User Id" ngModel name="user" [ERROR ->]#user="ngModel" required>
<app-input-validation-messages [model]="user"></app-input-validation-me"): ng:///DynamicTestModule/LoginComponent.html@9:102
Can't bind to 'model' since it isn't a known property of 'app-input-validation-messages'.
1. If 'app-input-validation-messages' is an Angular component and it has 'model' input, then verify that it is part of this module.
2. If 'app-input-validation-messages' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("ceholder="User Id" ngModel name="user" #user="ngModel" required>
<app-input-validation-messages [ERROR ->][model]="user"></app-input-validation-messages>
</div>
<div class="form-group">
"): ng:///DynamicTestModule/LoginComponent.html@10:35
'app-input-validation-messages' is not a known element:
1. If 'app-input-validation-messages' is an Angular component, then verify that it is part of this module.
2. If 'app-input-validation-messages' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("type="text" id="user-input" placeholder="User Id" ngModel name="user" #user="ngModel" required>
[ERROR ->]<app-input-validation-messages [model]="user"></app-input-validation-messages>

Error: <spyOn> : could not find an object to spy upon for login()
Usage: spyOn(<object>, <methodName>)
at SpyRegistry.spyOn (http://localhost:9877/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?da99c5b057693d025fad3d7685e1590600ca376d:4364:15)
at Env.spyOn (http://localhost:9877/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?da99c5b057693d025fad3d7685e1590600ca376d:925:32)
at spyOn (http://localhost:9877/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?da99c5b057693d025fad3d7685e1590600ca376d:4203:18)

不知道我在这里做错了什么。我搞砸了吗?

方法 3 - 似乎以某种方式起作用,但不确定我做了什么不同。然而,我无法弄清楚如何在下面的第二个测试中在这里测试组件的错误路径,即断言某些错误消息或其他内容。

describe('LoginComponent', () => {

let component: any;
let fixture: ComponentFixture<LoginComponent>;
let authenticationservice: any;
let router: Router;
let spyService: any;
let spyRouter: any;
let httpClient: HttpClient;

interface LoginRequest {
user: string;
password: string;
}


let creds: LoginRequest = {
user: "username",
password: "userpasswd"
}

let m: Config = {
}
let oToken: authToken = {
access_token: "abc",
token_type: "jj",
};

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
SharedModule,
FormsModule,
RouterTestingModule
],
declarations: [
LoginComponent
],
providers: [
]
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
authenticationservice = TestBed.get(AuthenticationService);
});








it('should login successfully', () => {
spyService = spyOn(authenticationservice, 'login').and.callFake(() => {
return Observable.of(oToken);
});
spyRouter = spyOn((<any>component).router, 'navigate');//.and.callThrough();
component.login({ value: creds });
expect(spyService).toHaveBeenCalledTimes(1);
expect(spyRouter).toHaveBeenCalledTimes(1);
});

it('should throw error message - bad credentials', () => {

spyService = spyOn(authenticationservice, 'login').and.returnValue(Observable.throw("Could not log in: Bad credentials"));
spyRouter = spyOn((<any>component).router, 'navigate');
var out = component.login({ value: creds });
console.log(":::::::"+out);
//how to put an assertion for Login Error Message here assuming that is returned by the catch block.
expect(spyService).toHaveBeenCalledTimes(1);
})
});

最佳答案

根据 the documentation :

You may also be able to get the service from the root injector via TestBed.get(). This is easier to remember and less verbose. But it only works when Angular injects the component with the service instance in the test's root injector.

所以也许你应该尝试使用注入(inject)器:

The safest way to get the injected service, the way that always works, is to get it from the injector of the component-under-test. The component injector is a property of the fixture's DebugElement.

authenticationservice = fixture.debugElement.injector.get(AuthenticationService)

编辑 尝试将依赖项直接注入(inject)到您的测试中

it('should login successfully', inject([AuthenticationService], (service: AuthenticationService) => {...}));

关于angular - < spy > : could not find an object to spy upon for login() - Angular TestBed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49427564/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com