问题是如果对象足够复杂(在任何强类型语言中),在Typescript中进行模拟可能会变得棘手。你通常会为了编译代码而模拟一些额外的东西,例如,在C#中你可以使用AutoFixture或类似的东西。另一方面,Javascript是动态语言,并且可以仅模拟测试运行所需的部分对象。
因此,在Typescript单元测试中,我可以使用any
类型声明我的依赖项,从而轻松模拟它。你看到这种方法的任何缺点吗?
let userServiceMock: MyApp.Services.UserService = {
// lots of thing to mock
}
VS
let userServiceMock: any = {
user: {
setting: {
showAvatar: true
}
}
}
答案 0 :(得分:15)
我在TypeScript中使用单元测试的经验肯定表明,保持所有模拟对象的输入值得。当你的模拟类型为data = [
[196, 242, 3],
[186, 302, 3],
[22, 377, 1],
[196, 377, 3],
....
]
user_count = max(i[0] for i in data) + 1
item_count = max(i[1] for i in data) + 1
data_mx = scipy.sparse.dok_matrix((user_count, item_count))
for (user, item, value) in data:
data_mx[user, item] = value
时,它会在重命名时出现问题。 IDE无法正确发现应更改any
或user
参数的出现位置。当然,使用完整的界面手动编写模拟对象真的很费力。
幸运的是,TypeScript有两种工具可以创建类型安全的模拟对象:ts-mockito(受Java mockito启发)和typemoq(受C# Moq启发)。< / p>
答案 1 :(得分:4)
现在TypeScript 3退出了,终于可以表达出完全强大的打字了!我利用了这一点,并将NSubstitute移植到TypeScript。
可以在这里找到:https://www.npmjs.com/package/@fluffy-spoon/substitute
我在这里与最流行的框架进行了比较:https://medium.com/@mathiaslykkegaardlorenzen/with-typescript-3-and-substitute-js-you-are-already-missing-out-when-mocking-or-faking-a3b3240c4607
请注意,它如何能够从界面中创建伪造品,并在此过程中进行充分的输入!
答案 2 :(得分:1)
正如@Terite any
所指出的那样,模拟是不好的选择,因为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);
还值得一提的是,Typescript不允许转换任何具有额外成员(超集或派生类型)的对象。表示您的部分模拟实际上是UserService
的基本类型,可以安全地进行投射。 e.g。
// 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
}
答案 3 :(得分:0)
对于功能对象,您可以使用支持Typescript的模拟库或具有类型定义的javascript库。在这两种情况下,类型仅在设计时存在。 因此,jasminesjs具有Spy功能,您可以像这样使用类型安全方式使用它:
DCE_unformat <- read.csv2(paste(getwd(),"/Data/data.csv",sep=""), header = TRUE)
DCE_unformat$P1 <- rep(0,4000)
DCE_unformat$P2 <- rep(0,4000)
DCE_unformat$P3 <- rep(0,4000)
for (i in 1:4000) {
if(DCE_unformat$Packaging[i] == "pallet") {
DCE_unformat$P1[i] <- 1
} else if (DCE_unformat$Packaging[i] == "container") {
DCE_unformat$P2[i] <- 1
} else if (DCE_unformat$Packaging[i] == "container en pallet") {
DCE_unformat$P3[i] <- 1
} else if (DCE_unformat$Packaging[i] == "other") {
DCE_unformat$P1[i] <- -1
DCE_unformat$P2[i] <- -1
DCE_unformat$P3[i] <- -1
}
}
IDE和Typescript编译器将正确处理它。唯一的缺点是不支持参数。如果您需要参数的类型支持,则需要使用Typescript模拟库。我可以为打字稿moq.ts
添加另一个模拟库对于DTO对象,您可以使用这种方法:
link = driver.find_element_by_link_text('Реестр товарных знаков и знаков обслуживания')
driver.execute_script('arguments[0].scrollIntoView();', link)
link.click()
我记得IDataMock可以用打字稿中的标准Partial接口代替。