在 TypeScript 中模拟只读 Flux 存储 属性

Mocking read-only Flux store property in TypeScript

我正在使用 React、Flux 和 TypeScript 创建一个应用程序。我正在使用 Karma 和 Jasmine 进行测试。

我有一家商店,像这样:

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 returns any). 但是,它在 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. In the above example I replace MemberStore completely with a jasmine SpyObj, which works. If instead I simply try to spyOn a real version of MemberStore, that's when I see a runtime error that members cannot be assigned. Example

我可以将其更改为 var mockMemberStore:any,或者使用像 (<any> mockMemberStore).members = [] 这样的转换,但是编译器不会将 members 视为对 ModelStore/members 的引用,所以所有静态类型检查丢失(并且 "find references" 和 "refactor/rename" 之类的东西不起作用)。这里使用的方法是什么?

你应该会写:

(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