如何使用 Jasmine 在 Angular 中测试我的服务?
How can I test my service in Angular with Jasmine?
我创建了一个如下所示的服务:
@Injectable({
providedIn: 'root'
})
export class NotificationService {
private notifications: Notification[] = []
private readonly notifications$: Subject<Notification[]> = new Subject()
getNotifications(): Observable<Notification[]> {
return this.notifications$
}
addNotification(config: Notification) {
const newNotification = {id: uuidv4(), ...config}
this.notifications.unshift(newNotification)
this.notifications$.next(this.notifications)
setTimeout(()=>{
this.removeNotification(newNotification.id)
}, 10000)
}
removeNotification(id: string): void {
this.notifications = this.notifications.filter(notifcation => notifcation.id !== id)
this.notifications$.next(this.notifications)
}
}
这被应用程序组件使用:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
notifications: Notification[]
constructor(notificationService: NotificationService) {
notificationService.getNotifications().subscribe(notifications =>
this.notifications = notifications
)
}
}
我想使用 Jasmine 测试此服务。这就是我的想法:
describe('Notification service', () => {
let service: NotificationService
beforeEach(() => {
service = new NotificationService()
})
it('should have no notifications initially',
() => {
service.getNotifications().subscribe(value => {
expect(value.length).toEqual(0)
})
}
)
it('should have one notification after adding a notification',
() => {
service.getNotifications().subscribe(value => {
expect(value.length).toEqual(1)
})
service.addNotification({
title: 'asdasdad',
message: 'asdasdasd',
type: 'info'
})
}
)
})
它最初应该没有通知:这是行不通的,因为即使我订阅了 getNotifications()
,next
函数中也没有任何值。我应该怎么期待
notifications
中的NotificationService
是空数组吗?
添加通知后它应该有一个通知:这个似乎正在工作并通过但我不喜欢我首先必须订阅 getNotifications()
我正在调用 addNotification()
在那之后。它违反了 Arrange、Act 和 Assert 模式。我怎样才能更好地编写这个测试?
我是这样解决的:
我将 notifications$
更改为 BehaviorSubject。这样,在订阅它的那一刻就发出了初始值。
...
export class NotificationService {
private notifications: NotificationConfig[] = []
private readonly subject: BehaviorSubject<NotificationConfig[]>
constructor() {
this.subject = new BehaviorSubject(this.notifications)
}
getNotifications(): Observable<NotificationConfig[]> {
return this.subject.asObservable()
}
...
和单元测试:
it('should have no notifications initially', () => {
let actualValue: NotificationConfig[] | undefined
service.getNotifications().subscribe(value => {
actualValue = value
}).unsubscribe()
expect(actualValue).toEqual([])
})
it('should have one right notification after adding a notification', () => {
const expectedNotification: NotificationConfig = {
...
}
service.addNotification(dummyNotification)
let actualValue: NotificationConfig[] | undefined
service.getNotifications().subscribe(value => {
actualValue = value
}).unsubscribe()
expect(actualValue.length).toEqual(1)
expect(actualValue[0]).toEqual(expectedNotification)
}
)
我创建了一个如下所示的服务:
@Injectable({
providedIn: 'root'
})
export class NotificationService {
private notifications: Notification[] = []
private readonly notifications$: Subject<Notification[]> = new Subject()
getNotifications(): Observable<Notification[]> {
return this.notifications$
}
addNotification(config: Notification) {
const newNotification = {id: uuidv4(), ...config}
this.notifications.unshift(newNotification)
this.notifications$.next(this.notifications)
setTimeout(()=>{
this.removeNotification(newNotification.id)
}, 10000)
}
removeNotification(id: string): void {
this.notifications = this.notifications.filter(notifcation => notifcation.id !== id)
this.notifications$.next(this.notifications)
}
}
这被应用程序组件使用:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
notifications: Notification[]
constructor(notificationService: NotificationService) {
notificationService.getNotifications().subscribe(notifications =>
this.notifications = notifications
)
}
}
我想使用 Jasmine 测试此服务。这就是我的想法:
describe('Notification service', () => {
let service: NotificationService
beforeEach(() => {
service = new NotificationService()
})
it('should have no notifications initially',
() => {
service.getNotifications().subscribe(value => {
expect(value.length).toEqual(0)
})
}
)
it('should have one notification after adding a notification',
() => {
service.getNotifications().subscribe(value => {
expect(value.length).toEqual(1)
})
service.addNotification({
title: 'asdasdad',
message: 'asdasdasd',
type: 'info'
})
}
)
})
它最初应该没有通知:这是行不通的,因为即使我订阅了 getNotifications()
,next
函数中也没有任何值。我应该怎么期待
notifications
中的NotificationService
是空数组吗?
添加通知后它应该有一个通知:这个似乎正在工作并通过但我不喜欢我首先必须订阅 getNotifications()
我正在调用 addNotification()
在那之后。它违反了 Arrange、Act 和 Assert 模式。我怎样才能更好地编写这个测试?
我是这样解决的:
我将 notifications$
更改为 BehaviorSubject。这样,在订阅它的那一刻就发出了初始值。
...
export class NotificationService {
private notifications: NotificationConfig[] = []
private readonly subject: BehaviorSubject<NotificationConfig[]>
constructor() {
this.subject = new BehaviorSubject(this.notifications)
}
getNotifications(): Observable<NotificationConfig[]> {
return this.subject.asObservable()
}
...
和单元测试:
it('should have no notifications initially', () => {
let actualValue: NotificationConfig[] | undefined
service.getNotifications().subscribe(value => {
actualValue = value
}).unsubscribe()
expect(actualValue).toEqual([])
})
it('should have one right notification after adding a notification', () => {
const expectedNotification: NotificationConfig = {
...
}
service.addNotification(dummyNotification)
let actualValue: NotificationConfig[] | undefined
service.getNotifications().subscribe(value => {
actualValue = value
}).unsubscribe()
expect(actualValue.length).toEqual(1)
expect(actualValue[0]).toEqual(expectedNotification)
}
)