我们说我们有一个班级
type ThisClassIsComplicated () =
let calculateSomething a b =
a + b
在这种情况下calculateSomething
是微不足道的,但如果它更复杂,那么验证那里完成的计算是否正确可能是有意义的。
使用unit testing framework来测试私有方法可能是有意义的。
我的问题:如何在F#中对私人方法进行单元测试?
一些随意的想法:
所选答案here建议使用InternalsVisibleTo
attribute,但无论如何仅适用于internal
methods。
特定于F#的路线是什么?这在F#设计中是否更好?
let calculateSomething a b = a + b
type ThisClassIsComplicated () =
member this.Calculate a b = calculateSomething a b
通过nested module可能甚至可以缩小calculateSomething
的范围。
答案 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
确实应该被广泛的世界所隐藏,但我认为它是该类内部契约的一部分。当然,您可以认为类视图数据和视图本身应该分开,但重点是:所有模型都不完美!