模拟打字稿单元测试

时间:2016-09-30 13:00:11

标签: javascript unit-testing typescript mocking

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

因此,在Typescript单元测试中,我可以使用any类型声明我的依赖项,从而轻松模拟它。你看到这种方法的任何缺点吗?

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

VS

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

4 个答案:

答案 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无法正确发现应更改anyuser参数的出现位置。当然,使用完整的界面手动编写模拟对象真的很费力。

幸运的是,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接口代替。