2016-09-30 63 views
7

问题是如果对象足够复杂(在任何强类型语言中),在Typescript中嘲讽会变得棘手。你通常会嘲笑一些额外的东西来编译代码,例如在C#中,你可以使用AutoFixture或类似的东西。另一方面,Javascript是动态语言,可以仅模拟测试运行所需的对象的一部分。在Typescript单元测试中嘲弄

因此,在Typescript单元测试中,我可以使用any类型声明我的依赖关系,因此可以轻松地对它进行嘲弄。你看到这种方法的缺点吗?

let userServiceMock: MyApp.Services.UserService = { 
    // lots of thing to mock 
} 

VS

let userServiceMock: any = { 
    user: { 
     setting: { 
      showAvatar: true 
     } 
    } 
} 

回答

10

我在打字稿单元测试经验肯定表明,这是值得保留所有键入的模仿对象。当你离开你的嘲笑类型any它在重命名期间变得有问题。 IDE将无法正确发现应该更改参数usersettings的哪些出现。当然用一个完整的界面手动编写模拟对象是非常费力的。

幸运的是,为打字稿,允许创建类型安全的模拟对象的两个工具:ts-mockito(由Java mockito启发)和typemoq(由C# Moq启发)。

+2

我写了一篇文章比较这两个库:https://medium.com/@michal.m.stocki/when-it-comes-to-mocking-in-typescript-be8531d39327 – Terite

+0

我写我自己的工具来处理这个相同的问题,并且我会喜欢它的一些反馈:https://medium.com/default-to-open/unit-testing-with-angular-and-ineeda-76746a0c8f58 – phenomnomnominal

1

正如@Terite any指出的,mock类型是不好的选择,因为mock和它的实际类型/实现之间没有关系。因此,改进方案可铸造部分嘲弄对象嘲笑类型:

export interface UserService { 
    getUser: (id: number) => User; 
    saveUser: (user: User) => void; 
    // ... number of other methods/fields 
} 

.......

let userServiceMock: UserService = <UserService> { 
    saveUser(user: User) { console.log("save user"); } 
} 
spyOn(userServiceMock, 'getUser').andReturn(new User()); 
expect(userServiceMock.getUser).toHaveBeenCalledWith(expectedUserId); 

还值得一提的是打字稿将不允许施放任何对象有额外的成员(超集或派生类型)。意味着你的部分模拟实际上是基本类型到UserService,并且可以安全地施放。例如

// Error: Neither type '...' nor 'UserService' is assignable to the other. 
let userServiceMock: UserService = <UserService> { 
    saveUser(user: User) { console.log("save user"); }, 
    extraFunc:() => { } // not available in UserService 
} 
+0

为什么,是对你有部分嘲笑的物体是如此重要?在同一服务中使用公共字段和公共方法是相当糟糕的主意。定义'setAvatarVisibility(visible:boolean)'方法会更好,并且保持'user'字段的私密性。那么你会避免手动间谍。请注意,在'spyOn(userServiceMock,'saveUser');'方法的字符串名称不会被IDE自动重构。 – Terite

+0

还有一个更好的解决方案是将用户对象保留在服务之外。如果我们保持服务无状态,代码更容易测试。你认为如何让'UserService'接收用户的方法:'saveUser(user:User):void;'? – Terite

+0

我只用这个代码作为例子,可能不是最好的,但它并不是我试图模拟的东西。我只是在寻找一个通用的解决方案。是的,你的例子当然更好,谢谢你的建议。 –