如何使用jasmine为注销服务正确编写单元测试?



我还是单元测试的新手,所以我想知道是否有人帮助我完成这个小任务。我用的是angular 8和jasmine。

这是我的登出服务:

import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LogoutService {
logout() {
const {protocol, hostname, port: locationPort} = window.location;
const port = locationPort ? `:${locationPort}` : '';
window.location.href =
`/oauth/logout?redirect=${protocol}//${hostname}${port}`;
}
}

这是我正在尝试的测试:

import { LogoutService } from './logout.service';
describe('LogoutService', () => {
let service;
beforeEach(() => {
service = new LogoutService();
});
it('should run #logout()', async () => {
let path = '/oauth/logout?redirect'
service.logout();
expect(window.location.href).toEqual(jasmine.objectContaining(path))
});
});

到目前为止,我正在尝试测试windows位置是否有协议&主机名&港口。

提前谢谢你。

首先,看起来您使用了错误的函数:根据官方文档,jasmine。objectcontains处理的不是字符串,而是json。

第二,您的目标是测试该窗口。位置包含协议等数据。所以检查'/oauth/logout?重定向'(你的路径变量)不是解决办法。

第三,您的服务设计说明了该窗口。location既可以作为输入(更准确地说是外部依赖),也可以作为测试的输出,再加上您似乎有全局变量locationPort作为另一个输入。为了实现有用的测试,您应该控制输入(控制输入可以简单地意味着重新分配窗口)。位置,但这可能会有问题;但是,这个问题可以通过重新设计注销方法来解决。

话虽如此,你可以试试这样做:

logout(wl: any) {
const {protocol, hostname, port: locationPort} = wl;
const port = locationPort ? `:${locationPort}` : '';
return `/oauth/logout?redirect=${protocol}//${hostname}${port}`;
}
it('should run #logout()', async () => {
const wl = { ...window.location, protocol: 'some-protocol', hostname: 'some-hostname' };
locationPort = 4200;
const href = service.logout(wl);
expect(href).toContain('some-protocol');
expect(href).toContain('some-hostname');
expect(href).toContain('4200');
// or
// expect(href).toContain(`some-protocol//some-hostname:4200`);
});

(当然,在您的应用程序中,您必须将注销方法的返回值分配给window.location.href)

我对logout方法所做的更改不仅仅是一个技术更改;它反映了单元测试如何让我们重新思考我们的代码设计。