问题
Let's say we have a class
type ThisClassIsComplicated () =
let calculateSomething a b =
a + b
In this case calculateSomething
is trivial, but if it would be more complicated it may make sense to verify that the calculations done there are correct.
It might make sense to use a unit testing framework to test that private methods.
My question: how to unit test private methods in F#?
Some random thoughts:
The selected answer here, suggests to use the InternalsVisibleTo attribute which anyway is applicable only to internalmethods.
What is the route specific to F# if any? Is this better in a F# design?
let calculateSomething a b = a + b
type ThisClassIsComplicated () =
member this.Calculate a b = calculateSomething a b
Maybe the scope of calculateSomething
could be even narrowed down by having a nested module.
回答1:
If you feel like your code is too complicated to test it from the outside, use the latter option. And in case you want to test an inner function like
let myComplicatedOperation input =
let calculateSomething a b =
a + b
calculateSomething (fst input) (snd input)
you can always rewrite it with currying like this:
let myComplicatedOperation calculateSomething input =
calculateSomething (fst input) (snd input)
Your question does not seem to be directly related to F# though. The general way to test private methods is typically by extracting a class (or, in F#, you can also just extract a let
bound function). And making your testee public on that other class / function.
回答2:
I think that loosening access restrictions in a class/module to facilitate testing is often a bad idea. If you have decided something is irrelevant to know for the outside world, you wanting to test it doesn't make it any less irrelevant.
Can't you just have a public method/function in your class/module that does the testing?
type ThisClassIsComplicated () =
let calculateSomething a b =
a + b
member private this.TestInstance () =
printfn "%A" <| calculateSomething 1 2
static member Test () =
(new ThisClassIsComplicated()).TestInstance()
回答3:
You can use Impromptu Interface to invoke private methods.
For example, I test the function calcNodeLabel
at
https://code.google.com/p/fseye/source/browse/trunk/FsEye/Forms/WatchTreeView.fs#73 like so: https://code.google.com/p/fseye/source/browse/trunk/Test.FsEye/WatchTreeViewLabelCalculatorTests.fs#54
But you need to be careful testing hidden functions in F#: it's an implementation detail of the compiler how the function will actually be compiled (e.g. as a method, as a delegate, as a ...).
Folks will warn generally against testing private methods, but I think it is a bit simplistic to say "never test private methods", since such a declaration takes for granted that access levels as specified in the .NET framework are the only way they could be.
For example, calcNodeLabel
in my example should indeed be hidden from the great wide world, but I would consider it part of the internal contract of the class. Of course, you could argue that the class view data and the view itself should be separated, but the point stands: all models are imperfect!
来源:https://stackoverflow.com/questions/22478427/unit-test-private-methods-in-f