[英]Mocking read-only Flux store property in TypeScript
I'm creating an app using React, Flux, and TypeScript. 我正在使用React,Flux和TypeScript创建一个应用程序。 I'm testing using Karma and Jasmine.
我正在使用Karma和Jasmine进行测试。
I have a Store, like this: 我有一家商店,像这样:
class MemberStore {
private _members:Member[];
public get members():Member[] { return this._members; }
}
As with all Flux stores, data is read-only and modified through action handlers (not shown), not setters. 与所有Flux商店一样,数据是只读的,并通过操作处理程序(未显示)而不是设置程序进行修改。
I would like to mock this data store in a unit test of code that depends on MemberStore
. 我想在依赖
MemberStore
的代码的单元测试中模拟此数据存储。 However, since members
is read-only I cannot do something like this: 但是,由于
members
是只读的,因此我无法执行以下操作:
var mockMemberStore:MemberStore = jasmine.createSpyObj("MemberStore");
mockMemberStore.members = [/*mock members*/];
The above code actually emits working JS, since mockMemberStore
is not actually an instance of MemberStore
but a Jasmine spy object (and createSpyObj
returns any
). 上面的代码实际上发出工作JS,因为
mockMemberStore
实际上不是的一个实例MemberStore
但茉莉间谍对象(和createSpyObj
返回any
)。 However, it generates a compile-error on mockMemberStore.members = []
because it's a read-only property.但是,由于它是只读属性,因此会在 mockMemberStore.members = []
上生成编译错误。
EDIT: So it turns out I was mis-reading the error, and it was not this code that gave an error.
编辑:原来我错读了错误,并且不是该代码提供了错误。 It was not a compile error, it's a runtime error.
这不是编译错误,而是运行时错误。 Surprisingly, TSC doesn't care if I assign a value to
members
at compile time, even though it's read-only.出乎意料的是,即使我是只读的,TSC也不在乎是否在编译时为
members
分配值。 In the above example I replaceMemberStore
completely with a jasmine SpyObj, which works.在上面的例子中,我代替
MemberStore
完全茉莉花SpyObj,它的工作原理。 If instead I simply try tospyOn
a real version ofMemberStore
, that's when I see a runtime error thatmembers
cannot be assigned.如果相反,我只是尝试
spyOn
一个真实版本的MemberStore
,那就是当我看到无法分配members
的运行时错误时。 Example例
I could change it to var mockMemberStore:any
, or use casting like (<any> mockMemberStore).members = []
, but then the compiler doesn't see members
as a reference to ModelStore/members
so all static type checking is lost (and things like "find references" and "refactor/rename" don't work). 我可以将其更改为
var mockMemberStore:any
,也可以使用(<any> mockMemberStore).members = []
,但是随后编译器没有将members
视为对ModelStore/members
的引用,因此所有静态类型检查都将丢失(并且“查找引用”和“重构/重命名”之类的内容不起作用)。 What is the approach to use here? 在这里使用什么方法?
You should be able to write: 您应该能够写:
(mockMemberStore as any).members = [""];
This will not change the type of any future references to mockMemberStore
. 这将不会更改任何将来对
mockMemberStore
引用的类型。 Because this is a unit test, the code does not need to be as perfect as it usually is. 由于这是一个单元测试,因此代码不需要像通常那样完美。 The important thing is that it will fail if you introduce an error, and in this case, it will fail: if you perform an invalid refactor,
renamedMembers
will no longer be set and the test should blow up, and you will be able to fix it. 重要的是,如果引入错误,它将失败,并且在这种情况下,它将失败:如果执行无效的重构,则将不再设置
renamedMembers
,并且测试应该renamedMembers
,并且您将能够修复它。
This is not ideal, since you do lose find-usages, but it's not as bad as it often is in other languages (mocking readonly objects is notoriously cumbersome). 这是不理想的,因为您会丢失查找用例,但是它并不像其他语言中那样糟糕(众所周知,嘲笑只读对象很麻烦)。
Interfaces are useful for this: 接口对此非常有用:
interface IMemberStore {
members: Member[];
}
class MemberStore implements IMemberStore {
private _members:Member[];
public get members():Member[] { return this._members; }
}
class MockMemberStore implements IMemberStore {
members: Member[];
}
Use IMemberStore
in most of your application, use MemberStore
as the implementation, and use MockMemberStore
in your unit tests. 使用
IMemberStore
在大多数应用程序,使用MemberStore
作为实现,并使用MockMemberStore
在单元测试中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.