【问题标题】:How can I test my service in Angular with Jasmine?如何使用 Jasmine 在 Angular 中测试我的服务?
【发布时间】:2021-08-17 12:57:28
【问题描述】:

我创建了一个如下所示的服务:

@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 函数中也没有任何价值。我应该怎么期待 NotificationService 中的notifications 是一个空数组?

添加通知后它应该有一个通知:这个似乎正在工作并通过但我不喜欢我首先必须订阅getNotifications(),然后我打电话给addNotification()。它违反了 Arrange、Act 和 Assert 模式。我怎样才能更好地编写这个测试?

【问题讨论】:

    标签: angular unit-testing jasmine observable


    【解决方案1】:

    我是这样解决的:

    我将 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)
        }
    )
    

    【讨论】:

    • 如果您能够解决您的问题,请接受您的回答作为解决方案。
    • @Rohlik 谢谢,我做到了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 2017-08-04
    相关资源
    最近更新 更多