2016-09-30 84 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

我只用這個代碼作爲例子,可能不是最好的,但它並不是我試圖模擬的東西。我只是在尋找一個通用的解決方案。是的,你的例子當然更好,謝謝你的建議。 –