【问题标题】:Unit Testing F# Code Throws Null Reference Exception, why?单元测试 F# 代码抛出空引用异常,为什么?
【发布时间】:2014-11-15 01:23:58
【问题描述】:

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

下面的代码执行精细编译或与 MEMOIZE 定义/未定义交互。但是,在未定义 MEMOIZE 的情况下,从 GUI NUnit 执行单元测试可以正常工作,但在定义 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 未定义时,我得到所有测试“绿色”,当它被定义时,所有测试都“红色”。

异常还是一样的:“Null Reference Exception”。但是,既然它在 IDE 中执行,我可以让调试器在异常时停止。到目前为止,我在断点处所能确定的只是它需要以下符号:

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

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

【问题讨论】:

  • 我猜你正在编译为 .exe 而不是 .dll 或者测试运行程序违反了一些 F# 假设。
  • 您使用的是哪个跑步者?对于在 VS2013 中使用内置运行器或使用 NUnit GUI 运行器的我来说,当我定义 MEMOIZE 时,您的代码按预期工作(我添加了一些打印以确保)。 Resharper 跑步者也可以工作,但测试显示两次,其中一半由于某种原因被跳过。
  • 查看我的原始帖子附录

标签: f# f#-interactive


【解决方案1】:

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

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

【讨论】:

  • 这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
  • 我有,但是 cmets 不能有多行代码,可以吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-19
  • 2011-03-17
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
相关资源
最近更新 更多