Unit Testing F# Code Throws Null Reference Exception, why?

230 views Asked by At

I'm using the NUnit testing technique suggested in the yet to be released book "F# Deep Dives Version 12" (Sec. 2.2 "Adding Tests")

The code below executes fine compiled or interactive with MEMOIZE defined/undefined. However, executing the unit test from the GUI NUnit works fine with MEMOIZE undefined, but it fails with a "Null Reference Exception" when MEMOIZE is defined. Notice memorize() uses a Closure. I'm suspecting the exception is happening because some initialization code generated by the compiler is not getting executed when NUnit starts up. What do you think?

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

UPDATE:

The standalone NUnit application is version 2.6.3.13283.

"FinnNk" gave me an idea! I installed Nuget package "NUnitTestAdapter". Now I can test directly within VS 2013. No surprises, though. I get all tests 'green' when MEMORIZE is undefined and all tests 'red' when it is defined.

The exception is still the same: "Null Reference Exception". However, now that it executes in the IDE, I can have the debugger stop on the exception. All I can determine so far at the breakpoint is that it needs the symbols from:

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

I installed the new VS 2015 Preview Edition. Nothing different happens in that environment. Now that .NET Framework is open source, maybe I can zero the debugger precisely on the problem with the source code for "mscorlib".

1

There are 1 answers

2
Tuomas Hietanen On

Are you running your NUnit tests in multiple threads? Normal dictionary is not thread-safe so weird things can happen. How about if you use ConcurrentDictionary, will it give the same result?

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