2013-04-08 66 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