我正在尝试根据当前用户详细信息测试显示或隐藏按钮的组件。我从服务上的方法中获取用户详细信息。该组件使用getter来调用服务方法。
在组件中:
get me() {
return this.sessionService.getMe()
}
在组件的html中:
<a id="profile-button" *ngIf="me.loggedIn" routerLink="profile">Profile</a>
我需要测试我登录时是否显示该按钮,并且在我未登录时未显示该按钮。我正在按如下方式对会话服务进行存根:
在组件规范文件中:
let sessionServiceStub = {
currentUser: {
loggedIn: false
}
getMe: function () {
return this.currentUser
}
}
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: ['RouterTestingModule'],
declarations: ['MyComponent'],
providers: [{provide: SessionService, useValue: sessionServiceStub}],
}).compileComponents()
}))
beforeEach(() => {
sessionServiceStub.currentUser = {
loggedIn = false
}
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
})
在每次测试开始时,我将服务存根上的loggedOn属性设置为true或false,然后调用detectChanges()
,但HTML不会按预期更新。这是与getter有关,如果是这样,我如何强制视图从sessionService获取新值?
在组件规范文件中:
it('shows the button when a user is logged in', () => {
sessionServiceStub.currentUser.loggedIn = true
fixture.detectChanges()
de = fixture.debugElement.query(By.css('#profile-button'))
el: HTMLAnchorElement = de.nativeElement // TypeError: Cannot read property 'nativeElement' of null
// ...
})
答案 0 :(得分:1)
从beforeEach方法中删除fixture.detectChanges()。
beforeEach(() => {
sessionServiceStub.currentUser = {
loggedIn = false
}
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
})
它应该可以正常工作。
答案 1 :(得分:1)
将sessionsServiceStub添加到providers数组时,会为测试创建一个新实例。在创建实例之后,我正在修改原始存根,并且在下一次测试(创建新实例时)之前这些更改不可用。
通过从存根中删除currentUser,对它进行的任何更改仍将可用于测试,因为新实例将引用相同的currentUser对象。
path
答案 2 :(得分:0)
您可能希望采用以下方法:describe
函数可以嵌套在其他describe
函数中。这使您可以将测试结构分成几个部分,这些部分将共享共同的锅炉板,如下所示。
警告:以下代码仅供参考,尚未经过测试。
describe('MyComponentUnderTestComponent', () => {
let component: MyComponentUnderTestComponent
let fixture: ComponentFixture<MyComponentUnderTestComponent>
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: ['RouterTestingModule'],
declarations: ['MyComponent'],
providers: [{provide: SessionService, useValue: sessionServiceStub}],
}).compileComponents()
}))
describe('when user is connected', () => {
beforeEach(() => {
sessionServiceStub.currentUser.loggedIn = true
fixture = TestBed.createComponent(MyComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
it('shows the button when a user is logged in', () => {
de = fixture.debugElement.query(By.css('#profile-button'))
el: HTMLAnchorElement = de.nativeElement
// ...
})
})
describe('when user is NOT connected', () => {
beforeEach(() => {
sessionServiceStub.currentUser.loggedIn = false
fixture = TestBed.createComponent(MyComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
})
it('does NOT show the button when a user is NOT logged in', () => {
de = fixture.debugElement.query(By.css('#profile-button'))
el: HTMLAnchorElement = de.nativeElement
// ...
})
})
这种方法在第一个站点稍微复杂一点,然后就是你所采用的方法。但是,它有几个好处:
嵌套describe
函数在测试中创建不同的上下文:“用户已登录”vs“用户未登录”。它有助于将锅炉板共享用于共享相同环境的测试。
因此,它会在您的文件中分隔完全不同的测试用例。
它使用beforeEach
函数来设置上下文(“用户已登录”,“用户未登录”)它应该是it
函数,而不是“在运行中”,在public function classWiseResult(Request $request){
$students = Students::where('class',$request->class)
->withCount(['firstTerm as firstTermPromoted' => function($q) {
$q->where('number', '>', 32);
}])
->withCount('firstTerm as firstTermAllCount')
->withCount(['secondTerm as secondTermPromoted' => function($q) {
$q->where('number', '>', 32);
}])
->withCount('secondTerm as secondTermAllCount')
->withCount(['finalTerm as finalTermPromoted' => function($q) {
$q->where('number', '>', 32);
}])
->withCount('finalTerm as finalTermAllCount')
->with('firstTerm')
->with('secondTerm')
->with('finalTerm')
->get();
return view('admin.showResult.show',compact('students'));
}
函数中,可能很难找到其他开发人员(即使是从现在开始的几天内自己)。