单元测试F#中的私有方法

时间:2014-03-18 11:46:21

标签: unit-testing f# private-members

我们说我们有一个班级

type ThisClassIsComplicated () = 
    let calculateSomething a b =
        a + b 

在这种情况下calculateSomething是微不足道的,但如果它更复杂,那么验证那里完成的计算是否正确可能是有意义的。

使用unit testing framework来测试私有方法可能是有意义的。

我的问题:如何在F#中对私人方法进行单元测试?

一些随意的想法:

所选答案here建议使用InternalsVisibleTo attribute,但无论如何仅适用于internalmethods

特定于F#的路线是什么?这在F#设计中是否更好?

let calculateSomething a b = a + b 

type ThisClassIsComplicated () = 
    member this.Calculate a b = calculateSomething a b

通过nested module可能甚至可以缩小calculateSomething的范围。

3 个答案:

答案 0 :(得分:4)

如果您觉得您的代码太复杂而无法从外部进行测试,请使用后一选项。如果你想测试像

这样的内部函数
let myComplicatedOperation input = 
    let calculateSomething a b =
        a + b
    calculateSomething (fst input) (snd input)

你总是可以像这样用currying重写它:

let myComplicatedOperation calculateSomething input =
    calculateSomething (fst input) (snd input)

你的问题似乎与F#没有直接关系。测试私有方法的一般方法通常是通过提取类(或者,在F#中,您也可以只提取let绑定函数)。并让你的被测者公开其他课程/功能。

答案 1 :(得分:3)

我认为放松类/模块中的访问限制以方便测试通常是一个坏主意。如果你已经确定某些东西与外界知道无关,你想要测试它并不会使它变得不那么无关紧要。

难道你不能在你的类/模块中有一个公共方法/函数来进行测试吗?

type ThisClassIsComplicated () = 
    let calculateSomething a b =
        a + b 

    member private this.TestInstance () = 
        printfn "%A" <| calculateSomething 1 2

    static member Test () = 
        (new ThisClassIsComplicated()).TestInstance()

答案 2 :(得分:3)

您可以使用Impromptu Interface来调用私有方法。

例如,我测试函数calcNodeLabel at https://code.google.com/p/fseye/source/browse/trunk/FsEye/Forms/WatchTreeView.fs#73喜欢这样:https://code.google.com/p/fseye/source/browse/trunk/Test.FsEye/WatchTreeViewLabelCalculatorTests.fs#54

但是你需要小心测试F#中的隐藏函数:它是编译器的实现细节,如何实际编译函数(例如作为方法,如代表,作为......)。

人们通常会警告不要测试私有方法,但我认为说“永不测试私有方法”有点过于简单,因为这样的声明理所当然地认为.NET框架中指定的访问级别是唯一的方法他们可以。

例如,我的例子中的calcNodeLabel确实应该被广泛的世界所隐藏,但我认为它是该类内部契约的一部分。当然,您可以认为类视图数据和视图本身应该分开,但重点是:所有模型都不完美!