Question

Since F# records are really sealed classes, i cannot stub a record type. Is there an attribute i can put on a record in F# so that it is not compiled as sealed so that i can stub the record?

type Quote = {a:string}

mock<Quote>

this throws

System.TypeLoadException : Could not load type 'Castle.Proxies.QuoteProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because the parent type is sealed.

And if you're curious. This is the definition for mock:

let mock<'typee when ^typee : not struct> = Substitute.For<'typee>()
Was it helpful?

Solution

I don't think there is a way to tell the F# compiler to generate F# record as a non-sealed class.

However, the question is, why do you want to stub a record? My understanding is that stubs are used to mimick some functionality of a type. However F# records are generated by the compiler, so if you trust the F# compiler, you should not need to mock them, because they will always behave predictably.

If you want to add some members to the record, then you can mock these. To do that you can define an interface, implement it in the record type and generate stub for the interface:

type IFoo = 
  abstract Foo : int -> int

type Bar = 
  { Number : int }
  interface IFoo with
    member x.Foo(n) = n + x.Number

In general, code written in a functional style can be tested just by checking whether an operation gives the correct result for a specified inputs. Testing that the internal implementation invokes some other operation (i.e. using stubs) is less needed. Of course, that probably does not always apply in real-world scenario where you interop with other components...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top