wil*_*bur 5 jasmine typescript angular
在乡亲中,这是一个繁重的代码。我试图将其最小化,但没有一些具体的例子,我看不出如何诊断这一点。
我在我的角度应用程序中为用户服务编写了以下模拟工厂。我们使用karma测试器运行器和jasmine测试框架。
万一重要的是,这里是我们karma和茉莉花测试的所有依赖项
"karma": "4.1.0",
"karma-chrome-launcher": "2.2.0",
"karma-coverage-istanbul-reporter": "2.0.3",
"karma-jasmine": "1.1.0",
"karma-jasmine-html-reporter": "1.3.1",
"karma-trx-reporter": "0.3.0",
"@types/jasmine": "2.8.3",
"@types/jasminewd2": "2.0.2",
"jasmine-core": "3.4.0",
"jasmine-spec-reporter": "4.2.1",
Run Code Online (Sandbox Code Playgroud)
模拟工厂
import {of, throwError} from 'rxjs';
import {CurrentUserModel} from '../models/api-data-models/current-user-model';
export class UserServiceMockFactory {
public static createUserServiceMock(jasmineSpyOn: any, jasmineSpyOnProperty: any, initialCurrentUserValue?: CurrentUserModel) {
const currentUserStub = {
// "as any" cast is essential here.
// It allows us to set valuePipedThroughCurrentUserGetter to values that are not of type CurrentUserModel.
// Most common use case would be an error
valuePipedThroughCurrentUserGetter: !!initialCurrentUserValue ? initialCurrentUserValue as any : null,
currentUserGetterThrows: false,
get currentUser() {
return !this.currentUserGetterThrows
? of(this.valuePipedThroughCurrentUserGetter)
: throwError(this.valuePipedThroughCurrentUserGetter);
},
currentUserGetSpy: null, // spy field to assert calls upon currentUser getter
flushCurrentUser() {
},
getUserBySearchTerm(term) {
}
};
currentUserStub.currentUserGetSpy = jasmineSpyOnProperty(currentUserStub, 'currentUser', 'get').and.callThrough();
jasmineSpyOn(currentUserStub, 'flushCurrentUser');
jasmineSpyOn(currentUserStub, 'getUserBySearchTerm');
return currentUserStub;
}
}
Run Code Online (Sandbox Code Playgroud)
其目的是为用户服务提供一个很好的预模拟实例,其中包含用户可能想要断言的所有间谍,以及通过设置来通过其他用户对象进行管道传输的选项valuePipedThroughCurrentUserGetter。
我已经编写了以下测试,并且测试取得了预期的成功。
it('should return new value if valuePipedThroughCurrentUserGetter changed, non-null initialization', () => {
const expectedCurrentUser = new CurrentUserModel({
id: '123',
login: 'jdoe',
isMaintenanceAndOperations: true,
isExcluder: true,
isSupport: true,
isImpersonator: true,
isViewAll: true,
initiators: [],
name: 'John Doe'
});
const userService = UserServiceMockFactory.createUserServiceMock(spyOn, spyOnProperty, new CurrentUserModel({
id: '123_a',
login: 'jdoe_a',
isMaintenanceAndOperations: false,
isExcluder: false,
isSupport: false,
isImpersonator: false,
isViewAll: false,
initiators: [],
name: 'John Doe_a'
}));
userService.valuePipedThroughCurrentUserGetter = expectedCurrentUser;
userService.currentUser
.subscribe(cu => expect(cu).toEqual(expectedCurrentUser),
() => fail('should not reach here'));
});
Run Code Online (Sandbox Code Playgroud)
但是,到了在实际测试中使用它的时候……它就崩溃了。我编写了以下最少的代码来隔离故障
import {TestBed} from '@angular/core/testing';
import {UserService} from '../http/user.service';
import {CurrentUserModel} from '../models/api-data-models/current-user-model';
import {UserServiceMockFactory} from './user-service-mock-factory';
describe('When Injected, Mock Behavior Seems to Fail', () => {
let userService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [{
provide: UserService,
useValue: UserServiceMockFactory.createUserServiceMock(spyOn, spyOnProperty,
new CurrentUserModel({
id: '123',
login: 'jdoe',
isMaintenanceAndOperations: true,
isExcluder: true,
isSupport: true,
isImpersonator: true,
isViewAll: true,
initiators: [],
name: 'John Doe'
}))
}]
});
userService = TestBed.get(UserService);
});
it('should succeed but fails :(', () => {
const expectedUser = new CurrentUserModel({
id: '123_a',
login: 'jdoe_a',
isMaintenanceAndOperations: false,
isExcluder: false,
isSupport: false,
isImpersonator: false,
isViewAll: false,
initiators: [],
name: 'John Doe_a'
});
userService.valuePipedThroughCurrentUserGetter = expectedUser;
userService.currentUser.subscribe(cu => {
expect(cu).toEqual(expectedUser);
});
});
});
Run Code Online (Sandbox Code Playgroud)
它失败,并显示以下消息
Expected $.id = '123' to equal '123_a'.
Expected $.login = 'jdoe' to equal 'jdoe_a'.
Expected $.isMaintenanceAndOperations = true to equal false.
Expected $.isExcluder = true to equal false.
Expected $.isSupport = true to equal false.
Expected $.isImpersonator = true to equal false.
Expected $.isViewAll = true to equal false.
Expected $.name = 'John Doe' to equal 'John Doe_a'.
Run Code Online (Sandbox Code Playgroud)
看起来,每当使用模拟服务来代替真实的服务currentUser时,即使它的支持字段很明显地改变了,它也无法更改从返回的值。
我发现奇怪的是,我可以通过修改UserServiceMockFactory使其稍有不同来使其表现出预期的效果。现在,我实现了似乎是同一个类的方法,而不是创建一个通用对象,然后对其进行监视,而是重新创建了它的一个实例,对该实例进行监视,然后瞧瞧!可以正常工作。
我的主要问题是:
为什么在替换实际服务时原始代码的行为会有所不同?
为什么在取代实际服务时新版本能按预期工作?
模拟工厂
import {of, throwError} from 'rxjs';
import {CurrentUserModel} from '../models/api-data-models/current-user-model';
class CurrentUserStub {
valuePipedThroughCurrentUserGetter: any;
currentUserGetterThrows = false;
constructor(init?) {
this.valuePipedThroughCurrentUserGetter = !!init ? init as any : null;
}
get currentUser() {
return !this.currentUserGetterThrows
? of(this.valuePipedThroughCurrentUserGetter)
: throwError(this.valuePipedThroughCurrentUserGetter);
}
currentUserGetSpy = null;
// spy field to assert calls upon currentUser getter
flushCurrentUser() {
}
getUserBySearchTerm(term) {
}
}
export class UserServiceMockFactory {
public static createUserServiceMock(jasmineSpyOn: any, jasmineSpyOnProperty: any, initialCurrentUserValue?: CurrentUserModel) {
const currentUserStub = new CurrentUserStub(initialCurrentUserValue);
currentUserStub.currentUserGetSpy = jasmineSpyOnProperty(currentUserStub, 'currentUser', 'get').and.callThrough();
jasmineSpyOn(currentUserStub, 'flushCurrentUser');
jasmineSpyOn(currentUserStub, 'getUserBySearchTerm');
return currentUserStub;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50 次 |
| 最近记录: |