我正在使用React,Flux和TypeScript创建一个应用程序。我正在使用业力和茉莉花进行测试。
我有一个商店,如下所示:
class MemberStore {
private _members:Member[];
public get members():Member[] { return this._members; }
}
与所有 Flux 存储一样,数据是只读的,并通过操作处理程序(未显示(而不是资源库进行修改。
我想在依赖于MemberStore
的代码单元测试中模拟此数据存储。但是,由于members
是只读的,因此我无法执行以下操作:
var mockMemberStore:MemberStore = jasmine.createSpyObj("MemberStore");
mockMemberStore.members = [/*mock members*/];
上面的代码实际上发出工作 JS,因为mockMemberStore
实际上不是 MemberStore
的实例,而是一个 Jasmine 间谍对象(并且createSpyObj
返回 any
(。但是,它会在mockMemberStore.members = []
上生成编译错误,因为它是只读属性。
编辑:所以事实证明我误读了错误,并不是这段代码给出了错误。这不是编译错误,而是运行时错误。令人惊讶的是,TSC 并不关心我是否在编译时为
members
分配一个值,即使 它是只读的。在上面的例子中,我替换了MemberStore
完全用茉莉花SpyObj,它有效。相反,如果我只是尝试spyOn
MemberStore
的真实版本,那就是我看到运行时错误的时候 无法分配members
。例
我可以将其更改为 var mockMemberStore:any
,或者像 (<any> mockMemberStore).members = []
一样使用强制转换,但随后编译器不会members
视为对ModelStore/members
的引用,因此所有静态类型检查都将丢失(并且诸如"查找引用"和"重构/重命名"之类的东西不起作用(。这里使用什么方法?
你应该能够写:
(mockMemberStore as any).members = [""];
这不会更改将来对 mockMemberStore
的任何引用的类型。因为这是一个单元测试,所以代码不需要像通常那样完美。重要的是,如果您引入错误,它将失败,在这种情况下,它将失败:如果您执行无效的重构,renamedMembers
将不再设置,测试应该会爆炸,您将能够修复它。
这并不理想,因为你确实丢失了查找用法,但它并不像其他语言中那样糟糕(模拟只读对象是出了名的麻烦(。
很有用:
interface IMemberStore {
members: Member[];
}
class MemberStore implements IMemberStore {
private _members:Member[];
public get members():Member[] { return this._members; }
}
class MockMemberStore implements IMemberStore {
members: Member[];
}
在大多数应用程序中使用 IMemberStore
,使用 MemberStore
作为实现,并在单元测试中使用MockMemberStore
。