单元测试F#代码抛出空引用异常,为什么?

时间:2014-11-15 01:23:58

标签: f# f#-interactive

我正在使用尚未发布的书“F#Deep Dives Version 12”中提出的NUnit测试技术(第2.2节“添加测试”)

以下代码使用 MEMOIZE 定义/未定义执行精细编译或交互。但是,从GUI NUnit执行单元测试可以正常工作 MEMOIZE 未定义,但是当定义 MEMOIZE 时,它会因“空引用异常”而失败。注意memorize()使用 Closure 。我怀疑发生了异常,因为当NUnit启动时,编译器生成的某些初始化代码没有被执行。你觉得怎么样?

open System
open System.Collections.Generic

open NUnit.Framework 
open FsUnit

let memoize (f: 'T -> 'U) =
    let t = new Dictionary<'T, 'U>(HashIdentity.Structural)
    fun n ->
        if t.ContainsKey n then t.[n]
        else let res = f n
             t.Add(n, res)
             res

//TODO: Insure J>0 & K>0 & J<K
let isMult = 
#if MEMOIZE
    memoize (fun (j,k) -> k % j = 0)
#else
    (fun (j,k) -> k % j = 0)
#endif

type ``Given the isMult function``() = 
    [<TestCase(3,1,false)>]
    [<TestCase(3,2,false)>]
    [<TestCase(3,3,true)>] 
    [<TestCase(5,10,true)>]
    [<TestCase(3,15,true)>]
    [<TestCase(5,13,false)>]
    [<TestCase(5,15,true)>]
    member t.``the result is calculated correctly``(j, k, expected) =         
        let actual = isMult (j,k)        
        actual |> should equal expected

更新

独立的NUnit应用程序是版本2.6.3.13283。

“FinnNk”给了我一个主意!我安装了Nuget包“NUnitTestAdapter”。现在我可以在VS 2013中直接测试。但是,没有惊喜。当MEMORIZE未定义时,我将所有测试设为“绿色”,并且在定义时,所有测试都为“红色”。

异常仍然相同:“空引用异常”。但是,现在它在IDE中执行,我可以让调试器停止在异常上。到目前为止我在断点处可以确定的是它需要以下符号:

C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.pdb

我安装了新的VS 2015预览版。在那种环境中没有任何不同。既然.NET Framework是开源的,也许我可以使用“mscorlib”的源代码精确地将调试器归零。

1 个答案:

答案 0 :(得分:0)

您是否在多个线程中运行NUnit测试?普通字典不是线程安全的,因此可能会发生奇怪的事情。如果你使用ConcurrentDictionary,它会给出相同的结果吗?

let memoize (f: 'T -> 'U) =
    let t = System.Collections.Concurrent.ConcurrentDictionary<'T, 'U>()
    fun n -> t.GetOrAdd(n, f)