2013-04-08 64 views
4

我想單元測試fun1而不調用fun2。如何在F#中打破函數依賴關係?

let fun2() = 
    // Some complex function with lots of dependencies. 
    1 

let fun1() = 
    fun2() * 2 

什麼是打破兩個函數之間依賴關係的最好方法?

我試過了幾種不同的方法,但它們只是增加了混亂。

通FUN2到FUN1

let fun1(fun2) = 
    fun2() * 2 

轉換爲一個類並重寫

type FunClass() = 
    abstract member fun2 : unit -> int 
    default x.fun2() = 1 

    member x.fun1() = 
     x.fun2() * 2 

type FunClassMock() = 
    override member x.fun2() = 1 

使用stategy模式

type Fun1Class(fun2Class) = 

    member x.fun1() = 
     fun2Class.fun2() * 2 

使用可變

let fun2Imp() = 
    1 

let mutable fun2 = fun2Imp 

let fun1() = 
    fun2() * 2 

有一個更清潔的方式?

+0

全局變量總是 – nicolas 2013-04-08 15:19:35

+1

我不想暗示有什麼不對您的問題的最佳解決方案 - 這是完全合法的 - 但我只是想知道你爲什麼要這麼做?它背後的真實情況是什麼? (我認爲這可能有助於找到正確的答案......) – 2013-04-08 17:32:55

+0

我在許多真實世界的場景中看到了這個問題。主要是財務計算。所以x = a + b/c,其中b和c是複雜計算的結果。在大多數情況下,我創建了類(aCalculator(),bCalculator())並將它們傳遞給我的xCalculator(),策略模式樣式,但這似乎並不實用,我想知道是否缺少更好的方法。 – 2013-04-09 13:35:47

回答

1

你這樣做的任何方式(我知道,至少)會「增加混亂」。這樣的事情呢?

let fun1() = 
    fun1_impl(fun2) 

let fun1_impl(fun2) = 
    fun2() * 2 

然後,在常規代碼,使用fun1,並且在測試中,使用fun1_impl

0

在所有概括性中,參數傳遞似乎是最乾淨的。

在技術上可能不會解決雜波效應,但是在語義上:它來自這樣一個事實,即它似乎有點武斷,因爲缺少賦予「function1」的含義。

在你的代碼中可能有更高,更一致的級別可能更有意義嗎?

3

這取決於你的使用情況,但你可以做這樣的事情:

let fun2() = 
    // Some complex function with lots of dependencies. 
    1 

let createFun1 fun2 = 
    fun() -> fun2() * 2 

let fun1 = createFun1 fun2 

這也是對單元測試有用,因爲你可以通過傳遞一個簡單的功能,在測試FUN2 FUN1。

2

它不是很靈活,但編譯器指令可以工作。

let fun2() = 
    #if TESTING 
    1 
    #else 
    // Some complex function with lots of dependencies. 
    #endif 

定義在單獨的模塊fun2open和荷蘭國際集團所需要的模塊是另一種選擇。

module Impl = 
    let fun2() = 
    // Some complex function with lots of dependencies. 

module Testing = 
    let fun2() = 1