mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-06 04:28:42 +00:00
Compare commits
1 Commits
2c539c13a3
...
WoofWare.M
Author | SHA1 | Date | |
---|---|---|---|
|
1b85182b9d |
@@ -1,5 +1,9 @@
|
||||
Notable changes are recorded here.
|
||||
|
||||
# WoofWare.Myriad.Plugins 8.1.1
|
||||
|
||||
Adds `GenerateCapturingMock`, which is `GenerateMock` but additionally records the calls made to each function.
|
||||
|
||||
# WoofWare.Myriad.Plugins 8.0.3
|
||||
|
||||
The RestEase-style HTTP client generator now automatically adds the `application/json` content type header to requests which are POSTing a body that is known to be JSON-serialised.
|
||||
|
@@ -5,7 +5,7 @@ open WoofWare.Myriad.Plugins
|
||||
|
||||
[<GenerateCapturingMock>]
|
||||
type IPublicType =
|
||||
abstract Mem1 : string * int -> string list
|
||||
abstract Mem1 : foo : string * int -> string list
|
||||
abstract Mem2 : string -> int
|
||||
abstract Mem3 : x : int * ?ct : System.Threading.CancellationToken -> string
|
||||
|
||||
@@ -36,9 +36,9 @@ type VeryPublicType<'a, 'b> =
|
||||
|
||||
[<GenerateCapturingMock>]
|
||||
type Curried<'a> =
|
||||
abstract Mem1 : int -> 'a -> string
|
||||
abstract Mem2 : int * string -> 'a -> string
|
||||
abstract Mem3 : (int * string) -> 'a -> string
|
||||
abstract Mem1 : bar : int -> 'a -> string
|
||||
abstract Mem2 : int * string -> baz : 'a -> string
|
||||
abstract Mem3 : quux : (int * string) -> flurb : 'a -> string
|
||||
abstract Mem4 : (int * string) -> ('a * int) -> string
|
||||
abstract Mem5 : x : int * string -> ('a * int) -> string
|
||||
abstract Mem6 : int * string -> y : 'a * int -> string
|
||||
|
@@ -9,285 +9,500 @@ namespace SomeNamespace.CapturingMock
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PublicTypeMockCalls =
|
||||
/// All the calls made to a PublicTypeMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
Mem3 : ResizeArray<int * System.Threading.CancellationToken option>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
Mem3 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal PublicTypeMock =
|
||||
{
|
||||
Calls : PublicTypeMockCalls.Calls
|
||||
Mem1 : string * int -> string list
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
Mem3 : int * option<System.Threading.CancellationToken> -> string
|
||||
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
|
||||
Mem3 : int * System.Threading.CancellationToken option -> string
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PublicTypeMock =
|
||||
{
|
||||
Calls = PublicTypeMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
Mem3_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface IPublicType with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
|
||||
member this.Mem3 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem3 (fun _ -> this.Calls.Mem3.Add (arg_0_0, arg_0_1))
|
||||
this.Mem3 (arg_0_0, arg_0_1)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module public PublicTypeInternalFalseMockCalls =
|
||||
/// All the calls made to a PublicTypeInternalFalseMock mock
|
||||
type public Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
Mem3 : ResizeArray<int * System.Threading.CancellationToken option>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
Mem3 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type public PublicTypeInternalFalseMock =
|
||||
{
|
||||
Calls : PublicTypeInternalFalseMockCalls.Calls
|
||||
Mem1 : string * int -> string list
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
Mem3 : int * option<System.Threading.CancellationToken> -> string
|
||||
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
|
||||
Mem3 : int * System.Threading.CancellationToken option -> string
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PublicTypeInternalFalseMock =
|
||||
{
|
||||
Calls = PublicTypeInternalFalseMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
Mem3_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface IPublicTypeInternalFalse with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
|
||||
member this.Mem3 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem3 (fun _ -> this.Calls.Mem3.Add (arg_0_0, arg_0_1))
|
||||
this.Mem3 (arg_0_0, arg_0_1)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal InternalTypeMockCalls =
|
||||
/// All the calls made to a InternalTypeMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal InternalTypeMock =
|
||||
{
|
||||
Calls : InternalTypeMockCalls.Calls
|
||||
Mem1 : string * int -> unit
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : InternalTypeMock =
|
||||
{
|
||||
Calls = InternalTypeMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface InternalType with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PrivateTypeMockCalls =
|
||||
/// All the calls made to a PrivateTypeMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type private PrivateTypeMock =
|
||||
{
|
||||
Calls : PrivateTypeMockCalls.Calls
|
||||
Mem1 : string * int -> unit
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PrivateTypeMock =
|
||||
{
|
||||
Calls = PrivateTypeMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface PrivateType with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PrivateTypeInternalFalseMockCalls =
|
||||
/// All the calls made to a PrivateTypeInternalFalseMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type private PrivateTypeInternalFalseMock =
|
||||
{
|
||||
Calls : PrivateTypeInternalFalseMockCalls.Calls
|
||||
Mem1 : string * int -> unit
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PrivateTypeInternalFalseMock =
|
||||
{
|
||||
Calls = PrivateTypeInternalFalseMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface PrivateTypeInternalFalse with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal VeryPublicTypeMockCalls =
|
||||
/// All the calls made to a VeryPublicTypeMock mock
|
||||
type internal Calls<'a, 'b> =
|
||||
{
|
||||
Mem1 : ResizeArray<'a>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls<'a, 'b> =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal VeryPublicTypeMock<'a, 'b> =
|
||||
{
|
||||
Calls : VeryPublicTypeMockCalls.Calls<'a, 'b>
|
||||
Mem1 : 'a -> 'b
|
||||
Mem1_Calls : ResizeArray<'a>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty () : VeryPublicTypeMock<'a, 'b> =
|
||||
{
|
||||
Calls = VeryPublicTypeMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface VeryPublicType<'a, 'b> with
|
||||
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
|
||||
member this.Mem1 arg_0_0 =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0))
|
||||
this.Mem1 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
/// A single call to the Mem1 method
|
||||
type internal Mem1Call<'a> =
|
||||
{
|
||||
arg0 : int
|
||||
arg1 : 'a
|
||||
}
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal CurriedMockCalls =
|
||||
/// A single call to the Mem1 method
|
||||
type internal Mem1Call<'a> =
|
||||
{
|
||||
bar : int
|
||||
Arg1 : 'a
|
||||
}
|
||||
|
||||
/// A single call to the Mem2 method
|
||||
type internal Mem2Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a
|
||||
}
|
||||
/// A single call to the Mem2 method
|
||||
type internal Mem2Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
baz : 'a
|
||||
}
|
||||
|
||||
/// A single call to the Mem3 method
|
||||
type internal Mem3Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a
|
||||
}
|
||||
/// A single call to the Mem3 method
|
||||
type internal Mem3Call<'a> =
|
||||
{
|
||||
quux : (int * string)
|
||||
flurb : 'a
|
||||
}
|
||||
|
||||
/// A single call to the Mem4 method
|
||||
type internal Mem4Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a * int
|
||||
}
|
||||
/// A single call to the Mem4 method
|
||||
type internal Mem4Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a * int
|
||||
}
|
||||
|
||||
/// A single call to the Mem5 method
|
||||
type internal Mem5Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a * int
|
||||
}
|
||||
/// A single call to the Mem5 method
|
||||
type internal Mem5Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a * int
|
||||
}
|
||||
|
||||
/// A single call to the Mem6 method
|
||||
type internal Mem6Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a * int
|
||||
}
|
||||
/// A single call to the Mem6 method
|
||||
type internal Mem6Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a * int
|
||||
}
|
||||
|
||||
/// All the calls made to a CurriedMock mock
|
||||
type internal Calls<'a> =
|
||||
{
|
||||
Mem1 : ResizeArray<Mem1Call<'a>>
|
||||
Mem2 : ResizeArray<Mem2Call<'a>>
|
||||
Mem3 : ResizeArray<Mem3Call<'a>>
|
||||
Mem4 : ResizeArray<Mem4Call<'a>>
|
||||
Mem5 : ResizeArray<Mem5Call<'a>>
|
||||
Mem6 : ResizeArray<Mem6Call<'a>>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls<'a> =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
Mem3 = ResizeArray ()
|
||||
Mem4 = ResizeArray ()
|
||||
Mem5 = ResizeArray ()
|
||||
Mem6 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal CurriedMock<'a> =
|
||||
{
|
||||
Calls : CurriedMockCalls.Calls<'a>
|
||||
Mem1 : int -> 'a -> string
|
||||
Mem1_Calls : ResizeArray<Mem1Call<'a>>
|
||||
Mem2 : int * string -> 'a -> string
|
||||
Mem2_Calls : ResizeArray<Mem2Call<'a>>
|
||||
Mem3 : (int * string) -> 'a -> string
|
||||
Mem3_Calls : ResizeArray<Mem3Call<'a>>
|
||||
Mem4 : (int * string) -> ('a * int) -> string
|
||||
Mem4_Calls : ResizeArray<Mem4Call<'a>>
|
||||
Mem5 : int * string -> ('a * int) -> string
|
||||
Mem5_Calls : ResizeArray<Mem5Call<'a>>
|
||||
Mem6 : int * string -> 'a * int -> string
|
||||
Mem6_Calls : ResizeArray<Mem6Call<'a>>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty () : CurriedMock<'a> =
|
||||
{
|
||||
Calls = CurriedMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||
Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4"))
|
||||
Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5"))
|
||||
Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem6"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
Mem3_Calls = ResizeArray ()
|
||||
Mem4_Calls = ResizeArray ()
|
||||
Mem5_Calls = ResizeArray ()
|
||||
Mem6_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface Curried<'a> with
|
||||
member this.Mem1 arg_0_0 arg_1_0 = this.Mem1 (arg_0_0) (arg_1_0)
|
||||
member this.Mem2 (arg_0_0, arg_0_1) arg_1_0 = this.Mem2 (arg_0_0, arg_0_1) (arg_1_0)
|
||||
member this.Mem3 ((arg_0_0, arg_0_1)) arg_1_0 = this.Mem3 (arg_0_0, arg_0_1) (arg_1_0)
|
||||
member this.Mem1 arg_0_0 arg_1_0 =
|
||||
lock
|
||||
this.Calls.Mem1
|
||||
(fun _ ->
|
||||
this.Calls.Mem1.Add
|
||||
{
|
||||
bar = arg_0_0
|
||||
Arg1 = arg_1_0
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem1 (arg_0_0) (arg_1_0)
|
||||
|
||||
member this.Mem2 (arg_0_0, arg_0_1) arg_1_0 =
|
||||
lock
|
||||
this.Calls.Mem2
|
||||
(fun _ ->
|
||||
this.Calls.Mem2.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
baz = arg_1_0
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem2 (arg_0_0, arg_0_1) (arg_1_0)
|
||||
|
||||
member this.Mem3 arg_0_0 arg_1_0 =
|
||||
lock
|
||||
this.Calls.Mem3
|
||||
(fun _ ->
|
||||
this.Calls.Mem3.Add
|
||||
{
|
||||
quux = arg_0_0
|
||||
flurb = arg_1_0
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem3 (arg_0_0) (arg_1_0)
|
||||
|
||||
member this.Mem4 ((arg_0_0, arg_0_1)) ((arg_1_0, arg_1_1)) =
|
||||
lock
|
||||
this.Calls.Mem4
|
||||
(fun _ ->
|
||||
this.Calls.Mem4.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0, arg_1_1
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem4 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
|
||||
|
||||
member this.Mem5 (arg_0_0, arg_0_1) ((arg_1_0, arg_1_1)) =
|
||||
lock
|
||||
this.Calls.Mem5
|
||||
(fun _ ->
|
||||
this.Calls.Mem5.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0, arg_1_1
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem5 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
|
||||
|
||||
member this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) =
|
||||
lock
|
||||
this.Calls.Mem6
|
||||
(fun _ ->
|
||||
this.Calls.Mem6.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0, arg_1_1
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal TypeWithInterfaceMockCalls =
|
||||
/// All the calls made to a TypeWithInterfaceMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string option>
|
||||
Mem2 : ResizeArray<unit>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal TypeWithInterfaceMock =
|
||||
{
|
||||
Calls : TypeWithInterfaceMockCalls.Calls
|
||||
/// Implementation of IDisposable.Dispose
|
||||
Dispose : unit -> unit
|
||||
Mem1 : string option -> string[] Async
|
||||
Mem1_Calls : ResizeArray<string option>
|
||||
Mem2 : unit -> string[] Async
|
||||
Mem2_Calls : ResizeArray<unit>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : TypeWithInterfaceMock =
|
||||
{
|
||||
Calls = TypeWithInterfaceMockCalls.Calls.Empty ()
|
||||
Dispose = (fun () -> ())
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface TypeWithInterface with
|
||||
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
|
||||
member this.Mem2 () = this.Mem2 (())
|
||||
member this.Mem1 arg_0_0 =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0))
|
||||
this.Mem1 (arg_0_0)
|
||||
|
||||
member this.Mem2 () =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (()))
|
||||
this.Mem2 (())
|
||||
|
||||
interface System.IDisposable with
|
||||
member this.Dispose () : unit = this.Dispose ()
|
||||
@@ -296,33 +511,50 @@ namespace SomeNamespace.CapturingMock
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal TypeWithPropertiesMockCalls =
|
||||
/// All the calls made to a TypeWithPropertiesMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string option>
|
||||
Prop1 : ResizeArray<unit>
|
||||
Prop2 : ResizeArray<unit>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Prop1 = ResizeArray ()
|
||||
Prop2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal TypeWithPropertiesMock =
|
||||
{
|
||||
Calls : TypeWithPropertiesMockCalls.Calls
|
||||
/// Implementation of IDisposable.Dispose
|
||||
Dispose : unit -> unit
|
||||
Prop1 : unit -> int
|
||||
Prop1_Calls : ResizeArray<unit>
|
||||
Prop2 : unit -> unit Async
|
||||
Prop2_Calls : ResizeArray<unit>
|
||||
Mem1 : string option -> string[] Async
|
||||
Mem1_Calls : ResizeArray<string option>
|
||||
Prop1 : unit -> int
|
||||
Prop2 : unit -> unit Async
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : TypeWithPropertiesMock =
|
||||
{
|
||||
Calls = TypeWithPropertiesMockCalls.Calls.Empty ()
|
||||
Dispose = (fun () -> ())
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Prop1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop1"))
|
||||
Prop2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop2"))
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Prop1_Calls = ResizeArray ()
|
||||
Prop2_Calls = ResizeArray ()
|
||||
Mem1_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface TypeWithProperties with
|
||||
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
|
||||
member this.Mem1 arg_0_0 =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0))
|
||||
this.Mem1 (arg_0_0)
|
||||
|
||||
member this.Prop1 = this.Prop1 ()
|
||||
member this.Prop2 = this.Prop2 ()
|
||||
|
||||
|
@@ -8,278 +8,493 @@ namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PublicTypeNoAttrMockCalls =
|
||||
/// All the calls made to a PublicTypeNoAttrMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
Mem3 : ResizeArray<int * System.Threading.CancellationToken option>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
Mem3 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal PublicTypeNoAttrMock =
|
||||
{
|
||||
Calls : PublicTypeNoAttrMockCalls.Calls
|
||||
Mem1 : string * int -> string list
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
Mem3 : int * option<System.Threading.CancellationToken> -> string
|
||||
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
|
||||
Mem3 : int * System.Threading.CancellationToken option -> string
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PublicTypeNoAttrMock =
|
||||
{
|
||||
Calls = PublicTypeNoAttrMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
Mem3_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface IPublicTypeNoAttr with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
|
||||
member this.Mem3 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem3 (fun _ -> this.Calls.Mem3.Add (arg_0_0, arg_0_1))
|
||||
this.Mem3 (arg_0_0, arg_0_1)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module public PublicTypeInternalFalseNoAttrMockCalls =
|
||||
/// All the calls made to a PublicTypeInternalFalseNoAttrMock mock
|
||||
type public Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
Mem3 : ResizeArray<int * System.Threading.CancellationToken option>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
Mem3 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type public PublicTypeInternalFalseNoAttrMock =
|
||||
{
|
||||
Calls : PublicTypeInternalFalseNoAttrMockCalls.Calls
|
||||
Mem1 : string * int -> string list
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
Mem3 : int * option<System.Threading.CancellationToken> -> string
|
||||
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
|
||||
Mem3 : int * System.Threading.CancellationToken option -> string
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PublicTypeInternalFalseNoAttrMock =
|
||||
{
|
||||
Calls = PublicTypeInternalFalseNoAttrMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
Mem3_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface IPublicTypeInternalFalseNoAttr with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
|
||||
member this.Mem3 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem3 (fun _ -> this.Calls.Mem3.Add (arg_0_0, arg_0_1))
|
||||
this.Mem3 (arg_0_0, arg_0_1)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal InternalTypeNoAttrMockCalls =
|
||||
/// All the calls made to a InternalTypeNoAttrMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal InternalTypeNoAttrMock =
|
||||
{
|
||||
Calls : InternalTypeNoAttrMockCalls.Calls
|
||||
Mem1 : string * int -> unit
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : InternalTypeNoAttrMock =
|
||||
{
|
||||
Calls = InternalTypeNoAttrMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface InternalTypeNoAttr with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PrivateTypeNoAttrMockCalls =
|
||||
/// All the calls made to a PrivateTypeNoAttrMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type private PrivateTypeNoAttrMock =
|
||||
{
|
||||
Calls : PrivateTypeNoAttrMockCalls.Calls
|
||||
Mem1 : string * int -> unit
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PrivateTypeNoAttrMock =
|
||||
{
|
||||
Calls = PrivateTypeNoAttrMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface PrivateTypeNoAttr with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PrivateTypeInternalFalseNoAttrMockCalls =
|
||||
/// All the calls made to a PrivateTypeInternalFalseNoAttrMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string * int>
|
||||
Mem2 : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type private PrivateTypeInternalFalseNoAttrMock =
|
||||
{
|
||||
Calls : PrivateTypeInternalFalseNoAttrMockCalls.Calls
|
||||
Mem1 : string * int -> unit
|
||||
Mem1_Calls : ResizeArray<string * int>
|
||||
Mem2 : string -> int
|
||||
Mem2_Calls : ResizeArray<string>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : PrivateTypeInternalFalseNoAttrMock =
|
||||
{
|
||||
Calls = PrivateTypeInternalFalseNoAttrMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface PrivateTypeInternalFalseNoAttr with
|
||||
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0)
|
||||
member this.Mem1 (arg_0_0, arg_0_1) =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
|
||||
this.Mem1 (arg_0_0, arg_0_1)
|
||||
|
||||
member this.Mem2 arg_0_0 =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (arg_0_0))
|
||||
this.Mem2 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal VeryPublicTypeNoAttrMockCalls =
|
||||
/// All the calls made to a VeryPublicTypeNoAttrMock mock
|
||||
type internal Calls<'a, 'b> =
|
||||
{
|
||||
Mem1 : ResizeArray<'a>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls<'a, 'b> =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal VeryPublicTypeNoAttrMock<'a, 'b> =
|
||||
{
|
||||
Calls : VeryPublicTypeNoAttrMockCalls.Calls<'a, 'b>
|
||||
Mem1 : 'a -> 'b
|
||||
Mem1_Calls : ResizeArray<'a>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty () : VeryPublicTypeNoAttrMock<'a, 'b> =
|
||||
{
|
||||
Calls = VeryPublicTypeNoAttrMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface VeryPublicTypeNoAttr<'a, 'b> with
|
||||
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
|
||||
member this.Mem1 arg_0_0 =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0))
|
||||
this.Mem1 (arg_0_0)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
/// A single call to the Mem1 method
|
||||
type internal Mem1Call<'a> =
|
||||
{
|
||||
arg0 : int
|
||||
arg1 : 'a
|
||||
}
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal CurriedNoAttrMockCalls =
|
||||
/// A single call to the Mem1 method
|
||||
type internal Mem1Call<'a> =
|
||||
{
|
||||
Arg0 : int
|
||||
Arg1 : 'a
|
||||
}
|
||||
|
||||
/// A single call to the Mem2 method
|
||||
type internal Mem2Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a
|
||||
}
|
||||
/// A single call to the Mem2 method
|
||||
type internal Mem2Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a
|
||||
}
|
||||
|
||||
/// A single call to the Mem3 method
|
||||
type internal Mem3Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a
|
||||
}
|
||||
/// A single call to the Mem3 method
|
||||
type internal Mem3Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a
|
||||
}
|
||||
|
||||
/// A single call to the Mem4 method
|
||||
type internal Mem4Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a * int
|
||||
}
|
||||
/// A single call to the Mem4 method
|
||||
type internal Mem4Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a * int
|
||||
}
|
||||
|
||||
/// A single call to the Mem5 method
|
||||
type internal Mem5Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a * int
|
||||
}
|
||||
/// A single call to the Mem5 method
|
||||
type internal Mem5Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a * int
|
||||
}
|
||||
|
||||
/// A single call to the Mem6 method
|
||||
type internal Mem6Call<'a> =
|
||||
{
|
||||
arg0 : int * string
|
||||
arg1 : 'a * int
|
||||
}
|
||||
/// A single call to the Mem6 method
|
||||
type internal Mem6Call<'a> =
|
||||
{
|
||||
Arg0 : int * string
|
||||
Arg1 : 'a * int
|
||||
}
|
||||
|
||||
/// All the calls made to a CurriedNoAttrMock mock
|
||||
type internal Calls<'a> =
|
||||
{
|
||||
Mem1 : ResizeArray<Mem1Call<'a>>
|
||||
Mem2 : ResizeArray<Mem2Call<'a>>
|
||||
Mem3 : ResizeArray<Mem3Call<'a>>
|
||||
Mem4 : ResizeArray<Mem4Call<'a>>
|
||||
Mem5 : ResizeArray<Mem5Call<'a>>
|
||||
Mem6 : ResizeArray<Mem6Call<'a>>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls<'a> =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
Mem3 = ResizeArray ()
|
||||
Mem4 = ResizeArray ()
|
||||
Mem5 = ResizeArray ()
|
||||
Mem6 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal CurriedNoAttrMock<'a> =
|
||||
{
|
||||
Calls : CurriedNoAttrMockCalls.Calls<'a>
|
||||
Mem1 : int -> 'a -> string
|
||||
Mem1_Calls : ResizeArray<Mem1Call<'a>>
|
||||
Mem2 : int * string -> 'a -> string
|
||||
Mem2_Calls : ResizeArray<Mem2Call<'a>>
|
||||
Mem3 : (int * string) -> 'a -> string
|
||||
Mem3_Calls : ResizeArray<Mem3Call<'a>>
|
||||
Mem4 : (int * string) -> ('a * int) -> string
|
||||
Mem4_Calls : ResizeArray<Mem4Call<'a>>
|
||||
Mem5 : int * string -> ('a * int) -> string
|
||||
Mem5_Calls : ResizeArray<Mem5Call<'a>>
|
||||
Mem6 : int * string -> 'a * int -> string
|
||||
Mem6_Calls : ResizeArray<Mem6Call<'a>>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty () : CurriedNoAttrMock<'a> =
|
||||
{
|
||||
Calls = CurriedNoAttrMockCalls.Calls.Empty ()
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||
Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4"))
|
||||
Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5"))
|
||||
Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem6"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
Mem3_Calls = ResizeArray ()
|
||||
Mem4_Calls = ResizeArray ()
|
||||
Mem5_Calls = ResizeArray ()
|
||||
Mem6_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface CurriedNoAttr<'a> with
|
||||
member this.Mem1 arg_0_0 arg_1_0 = this.Mem1 (arg_0_0) (arg_1_0)
|
||||
member this.Mem2 (arg_0_0, arg_0_1) arg_1_0 = this.Mem2 (arg_0_0, arg_0_1) (arg_1_0)
|
||||
member this.Mem3 ((arg_0_0, arg_0_1)) arg_1_0 = this.Mem3 (arg_0_0, arg_0_1) (arg_1_0)
|
||||
member this.Mem1 arg_0_0 arg_1_0 =
|
||||
lock
|
||||
this.Calls.Mem1
|
||||
(fun _ ->
|
||||
this.Calls.Mem1.Add
|
||||
{
|
||||
Arg0 = arg_0_0
|
||||
Arg1 = arg_1_0
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem1 (arg_0_0) (arg_1_0)
|
||||
|
||||
member this.Mem2 (arg_0_0, arg_0_1) arg_1_0 =
|
||||
lock
|
||||
this.Calls.Mem2
|
||||
(fun _ ->
|
||||
this.Calls.Mem2.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem2 (arg_0_0, arg_0_1) (arg_1_0)
|
||||
|
||||
member this.Mem3 ((arg_0_0, arg_0_1)) arg_1_0 =
|
||||
lock
|
||||
this.Calls.Mem3
|
||||
(fun _ ->
|
||||
this.Calls.Mem3.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem3 (arg_0_0, arg_0_1) (arg_1_0)
|
||||
|
||||
member this.Mem4 ((arg_0_0, arg_0_1)) ((arg_1_0, arg_1_1)) =
|
||||
lock
|
||||
this.Calls.Mem4
|
||||
(fun _ ->
|
||||
this.Calls.Mem4.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0, arg_1_1
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem4 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
|
||||
|
||||
member this.Mem5 (arg_0_0, arg_0_1) ((arg_1_0, arg_1_1)) =
|
||||
lock
|
||||
this.Calls.Mem5
|
||||
(fun _ ->
|
||||
this.Calls.Mem5.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0, arg_1_1
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem5 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
|
||||
|
||||
member this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) =
|
||||
lock
|
||||
this.Calls.Mem6
|
||||
(fun _ ->
|
||||
this.Calls.Mem6.Add
|
||||
{
|
||||
Arg0 = arg_0_0, arg_0_1
|
||||
Arg1 = arg_1_0, arg_1_1
|
||||
}
|
||||
)
|
||||
|
||||
this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
|
||||
namespace SomeNamespace.CapturingMock
|
||||
|
||||
open System
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal TypeWithInterfaceNoAttrMockCalls =
|
||||
/// All the calls made to a TypeWithInterfaceNoAttrMock mock
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<string option>
|
||||
Mem2 : ResizeArray<unit>
|
||||
}
|
||||
|
||||
/// A fresh calls object which has not yet had any calls made.
|
||||
static member Empty () : Calls =
|
||||
{
|
||||
Mem1 = ResizeArray ()
|
||||
Mem2 = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal TypeWithInterfaceNoAttrMock =
|
||||
{
|
||||
Calls : TypeWithInterfaceNoAttrMockCalls.Calls
|
||||
/// Implementation of IDisposable.Dispose
|
||||
Dispose : unit -> unit
|
||||
Mem1 : string option -> string[] Async
|
||||
Mem1_Calls : ResizeArray<string option>
|
||||
Mem2 : unit -> string[] Async
|
||||
Mem2_Calls : ResizeArray<unit>
|
||||
}
|
||||
|
||||
/// An implementation where every non-unit method throws.
|
||||
static member Empty : TypeWithInterfaceNoAttrMock =
|
||||
{
|
||||
Calls = TypeWithInterfaceNoAttrMockCalls.Calls.Empty ()
|
||||
Dispose = (fun () -> ())
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||
Mem1_Calls = ResizeArray ()
|
||||
Mem2_Calls = ResizeArray ()
|
||||
}
|
||||
|
||||
interface TypeWithInterfaceNoAttr with
|
||||
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
|
||||
member this.Mem2 () = this.Mem2 (())
|
||||
member this.Mem1 arg_0_0 =
|
||||
lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0))
|
||||
this.Mem1 (arg_0_0)
|
||||
|
||||
member this.Mem2 () =
|
||||
lock this.Calls.Mem2 (fun _ -> this.Calls.Mem2.Add (()))
|
||||
this.Mem2 (())
|
||||
|
||||
interface System.IDisposable with
|
||||
member this.Dispose () : unit = this.Dispose ()
|
||||
|
89
README.md
89
README.md
@@ -13,7 +13,7 @@ Currently implemented:
|
||||
* `JsonParse` (to stamp out `jsonParse : JsonNode -> 'T` methods).
|
||||
* `JsonSerialize` (to stamp out `toJsonNode : 'T -> JsonNode` methods).
|
||||
* `HttpClient` (to stamp out a [RestEase](https://github.com/canton7/RestEase)-style HTTP client).
|
||||
* `GenerateMock` (to stamp out a record type corresponding to an interface, like a compile-time [Foq](https://github.com/fsprojects/Foq)).
|
||||
* `GenerateMock` and `GenerateCapturingMock` (to stamp out a record type corresponding to an interface, like a compile-time [Foq](https://github.com/fsprojects/Foq)).
|
||||
* `ArgParser` (to stamp out a basic argument parser).
|
||||
* `SwaggerClient` (to stamp out an HTTP client for a Swagger API).
|
||||
* `CreateCatamorphism` (to stamp out a non-stack-overflowing [catamorphism](https://fsharpforfunandprofit.com/posts/recursive-types-and-folds/) for a discriminated union).
|
||||
@@ -440,9 +440,9 @@ There are also some design decisions:
|
||||
so arguments are forced to be tupled.
|
||||
* The `[<Optional>]` attribute is not supported and will probably not be supported, because I consider it to be cursed.
|
||||
|
||||
## `GenerateMock`
|
||||
## `GenerateMock` and `GenerateCapturingMock`
|
||||
|
||||
Takes a type like this:
|
||||
`GenerateMock` takes a type like this:
|
||||
|
||||
```fsharp
|
||||
[<GenerateMock>]
|
||||
@@ -472,6 +472,59 @@ type internal PublicTypeMock =
|
||||
member this.Mem2 (arg0) = this.Mem2 (arg0)
|
||||
```
|
||||
|
||||
`GenerateCapturingMock` additionally captures the calls made to each function (except for `Dispose`).
|
||||
It takes a type like this:
|
||||
|
||||
```fsharp
|
||||
[<GenerateCapturingMock>]
|
||||
type IPublicType =
|
||||
abstract Mem1 : string * int -> thing : bool -> string list
|
||||
abstract Mem2 : baz : string -> unit -> int
|
||||
```
|
||||
|
||||
and stamps out types like this:
|
||||
|
||||
```fsharp
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PublicTypeCalls =
|
||||
type internal Mem1Call =
|
||||
{
|
||||
Arg0 : string * int
|
||||
thing : bool
|
||||
}
|
||||
|
||||
type internal Calls =
|
||||
{
|
||||
Mem1 : ResizeArray<Mem1Call>
|
||||
Mem2 : ResizeArray<string>
|
||||
}
|
||||
|
||||
static member Empty () = { Mem1 = ResizeArray () ; Mem2 = ResizeArray () }
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal PublicTypeMock =
|
||||
{
|
||||
Mem1 : string * int -> bool -> string list
|
||||
Mem2 : string -> int
|
||||
Calls : PublicTypeCalls.Calls
|
||||
}
|
||||
|
||||
static member Empty : PublicTypeMock =
|
||||
{
|
||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||
Calls = PublicTypeMockCalls.Calls.Empty ()
|
||||
}
|
||||
|
||||
interface IPublicType with
|
||||
member this.Mem1 (arg0, arg1) =
|
||||
lock this.Calls.Mem1 (fun () -> this.Calls.Mem1.Add { Arg0 = arg0 ; thing = arg1 })
|
||||
this.Mem1 (arg0, arg1)
|
||||
member this.Mem2 (arg0) =
|
||||
lock this.Calls.Mem2 (fun () -> this.Calls.Mem2.Add arg0)
|
||||
this.Mem2 (arg0)
|
||||
```
|
||||
|
||||
### What's the point?
|
||||
|
||||
Reflective mocking libraries like [Foq](https://github.com/fsprojects/Foq) in my experience are a rich source of flaky tests.
|
||||
@@ -483,6 +536,36 @@ thereby allowing the programmer to use F#'s record-update syntax.
|
||||
|
||||
* You may supply an `isInternal : bool` argument to the attribute. By default, we make the resulting record type at most internal (never public), since this is intended only to be used in tests; but you can instead make it public with `[<GenerateMock false>]`.
|
||||
|
||||
### Gotchas (GenerateCapturingMock)
|
||||
|
||||
We use the same name for the record field as the implementing interface member:
|
||||
|
||||
```fsharp
|
||||
type FooMock =
|
||||
{
|
||||
Field : string -> unit
|
||||
}
|
||||
interface IFoo with
|
||||
member _.Field x = ...
|
||||
```
|
||||
|
||||
If you have an object of type `FooMock` in scope, you'll get the *record field*, not the *interface member*.
|
||||
You need to cast it to `IFoo` before using it (or pass it into a function which takes an `IFoo`):
|
||||
|
||||
```fsharp
|
||||
let thing = FooMock.Empty () // of type FooMock
|
||||
thing.Field "hello" // the wrong one! bypasses the IFoo implementation which captures calls
|
||||
|
||||
// correct:
|
||||
let thing' = FooMock.Empty ()
|
||||
let thing = thing' :> IFoo
|
||||
thing.Field "hello" // the right one: this call does get recorded in the mock, because this is the interface member
|
||||
|
||||
// also correct, but beware because it leaves the chance of the above footgun lying around for later:
|
||||
let thing = FooMock.Empty () // of type FooMock
|
||||
doTheThing thing // where doTheThing : IFoo -> unit
|
||||
```
|
||||
|
||||
## `CreateCatamorphism`
|
||||
|
||||
Takes a collection of mutually recursive discriminated unions:
|
||||
|
@@ -32,7 +32,11 @@ type GenerateMockAttribute (isInternal : bool) =
|
||||
/// record update syntax to easily specify partially-implemented mock objects.
|
||||
/// You may optionally specify `isInternal = false` to get a mock with the public visibility modifier.
|
||||
///
|
||||
/// The default implementation of each field captures all calls made to it, which can then be accessed later.
|
||||
/// The default implementation of each field throws.
|
||||
///
|
||||
/// The generated interface methods capture all calls made to them, before passing through to the relevant
|
||||
/// field of the mock record; the calls can be accessed later through the `Calls` field of the generated
|
||||
/// mock record.
|
||||
type GenerateCapturingMockAttribute (isInternal : bool) =
|
||||
inherit Attribute ()
|
||||
/// The default value of `isInternal`, the optional argument to the GenerateCapturingMockAttribute constructor.
|
||||
|
@@ -15,6 +15,11 @@ WoofWare.Myriad.Plugins.ArgumentLongForm inherit System.Attribute
|
||||
WoofWare.Myriad.Plugins.ArgumentLongForm..ctor [constructor]: string
|
||||
WoofWare.Myriad.Plugins.CreateCatamorphismAttribute inherit System.Attribute
|
||||
WoofWare.Myriad.Plugins.CreateCatamorphismAttribute..ctor [constructor]: string
|
||||
WoofWare.Myriad.Plugins.GenerateCapturingMockAttribute inherit System.Attribute
|
||||
WoofWare.Myriad.Plugins.GenerateCapturingMockAttribute..ctor [constructor]: bool
|
||||
WoofWare.Myriad.Plugins.GenerateCapturingMockAttribute..ctor [constructor]: unit
|
||||
WoofWare.Myriad.Plugins.GenerateCapturingMockAttribute.DefaultIsInternal [static property]: [read-only] bool
|
||||
WoofWare.Myriad.Plugins.GenerateCapturingMockAttribute.get_DefaultIsInternal [static method]: unit -> bool
|
||||
WoofWare.Myriad.Plugins.GenerateMockAttribute inherit System.Attribute
|
||||
WoofWare.Myriad.Plugins.GenerateMockAttribute..ctor [constructor]: bool
|
||||
WoofWare.Myriad.Plugins.GenerateMockAttribute..ctor [constructor]: unit
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "3.6",
|
||||
"version": "3.7",
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/main$"
|
||||
],
|
||||
|
@@ -6,7 +6,7 @@ open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
|
||||
[<TestFixture>]
|
||||
module TestMockGenerator =
|
||||
module TestCapturingMockGenerator =
|
||||
|
||||
[<Test>]
|
||||
let ``Example of use: IPublicType`` () =
|
||||
@@ -47,3 +47,26 @@ module TestMockGenerator =
|
||||
mock.Mem1 (Some "hi") |> Async.RunSynchronously |> shouldEqual [| "hi" |]
|
||||
|
||||
mock.Prop1 |> shouldEqual 44
|
||||
|
||||
[<Test>]
|
||||
let ``Example of curried use`` () =
|
||||
let mock' =
|
||||
{ CurriedMock<string>.Empty () with
|
||||
Mem1 =
|
||||
fun x y ->
|
||||
x |> shouldEqual 3
|
||||
y |> shouldEqual "hello"
|
||||
"it's me"
|
||||
}
|
||||
|
||||
let mock = mock' :> Curried<_>
|
||||
|
||||
mock.Mem1 3 "hello" |> shouldEqual "it's me"
|
||||
|
||||
lock mock'.Calls.Mem1 (fun () -> Seq.toList mock'.Calls.Mem1)
|
||||
|> List.exactlyOne
|
||||
|> shouldEqual
|
||||
{
|
||||
bar = 3
|
||||
Arg1 = "hello"
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
|
||||
[<TestFixture>]
|
||||
module TestCapturingMockGeneratorNoAttr =
|
||||
module TestMockGeneratorNoAttr =
|
||||
|
||||
[<Test>]
|
||||
let ``Example of use: IPublicType`` () =
|
@@ -28,7 +28,9 @@
|
||||
<Compile Include="TestHttpClient\TestVaultClient.fs" />
|
||||
<Compile Include="TestHttpClient\TestVariableHeader.fs" />
|
||||
<Compile Include="TestMockGenerator\TestMockGenerator.fs" />
|
||||
<Compile Include="TestMockGenerator\TestCapturingMockGeneratorNoAttr.fs" />
|
||||
<Compile Include="TestMockGenerator\TestMockGeneratorNoAttr.fs" />
|
||||
<Compile Include="TestCapturingMockGenerator\TestCapturingMockGenerator.fs" />
|
||||
<Compile Include="TestCapturingMockGenerator\TestCapturingMockGeneratorNoAttr.fs" />
|
||||
<Compile Include="TestJsonSerialize\TestJsonSerde.fs" />
|
||||
<Compile Include="TestCataGenerator\TestCataGenerator.fs" />
|
||||
<Compile Include="TestCataGenerator\TestDirectory.fs" />
|
||||
@@ -67,9 +69,4 @@
|
||||
<ProjectReference Include="..\ConsumePlugin\ConsumePlugin.fsproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="TestCapturingMockGenerator\TestCapturingMockGenerator.fs" />
|
||||
<Compile Include="TestCapturingMockGenerator\TestCapturingMockGeneratorNoAttr.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -41,11 +41,21 @@ module internal CapturingInterfaceMockGenerator =
|
||||
args
|
||||
|> List.mapi (fun i tupledArg ->
|
||||
{
|
||||
SynFieldData.Ident = $"arg%i{i}" |> Ident.create |> Some
|
||||
SynFieldData.Ident =
|
||||
match tupledArg.Args with
|
||||
| [ arg ] -> arg.Id
|
||||
| _ -> None
|
||||
|> Option.defaultValue (Ident.create $"Arg%i{i}")
|
||||
|> Some
|
||||
Attrs = []
|
||||
Type =
|
||||
tupledArg.Args
|
||||
|> List.map (fun pi -> pi.Type)
|
||||
|> List.map (fun pi ->
|
||||
if pi.IsOptional then
|
||||
pi.Type |> SynType.appPostfix "option"
|
||||
else
|
||||
pi.Type
|
||||
)
|
||||
|> SynType.tupleNoParen
|
||||
|> Option.get
|
||||
}
|
||||
@@ -70,7 +80,7 @@ module internal CapturingInterfaceMockGenerator =
|
||||
|
||||
let private buildType (x : ParameterInfo) : SynType =
|
||||
if x.IsOptional then
|
||||
SynType.app "option" [ x.Type ]
|
||||
SynType.appPostfix "option" x.Type
|
||||
else
|
||||
x.Type
|
||||
|
||||
@@ -115,12 +125,7 @@ module internal CapturingInterfaceMockGenerator =
|
||||
|
||||
/// Builds the record field for the mock object, and also if applicable a type representing a single call to
|
||||
/// that object (packaging up the args of the call).
|
||||
let private constructMember
|
||||
(spec : CapturingInterfaceMockOutputSpec)
|
||||
(generics : SynTyparDecls option)
|
||||
(mem : MemberInfo)
|
||||
: SynField * CallField
|
||||
=
|
||||
let private constructMember (spec : CapturingInterfaceMockOutputSpec) (mem : MemberInfo) : SynField * CallField =
|
||||
let inputType = mem.Args |> List.map constructMemberSinglePlace
|
||||
|
||||
let funcType = SynType.toFun inputType mem.ReturnType
|
||||
@@ -139,7 +144,12 @@ module internal CapturingInterfaceMockGenerator =
|
||||
| [] -> failwith "expected args in member"
|
||||
| [ ty ] ->
|
||||
ty.Args
|
||||
|> List.map _.Type
|
||||
|> List.map (fun pi ->
|
||||
if pi.IsOptional then
|
||||
SynType.appPostfix "option" pi.Type
|
||||
else
|
||||
pi.Type
|
||||
)
|
||||
|> SynType.tupleNoParen
|
||||
|> Option.get
|
||||
|> CallField.Original
|
||||
@@ -179,11 +189,11 @@ module internal CapturingInterfaceMockGenerator =
|
||||
(name : string)
|
||||
(interfaceType : InterfaceType)
|
||||
(xmlDoc : PreXmlDoc)
|
||||
: SynModuleDecl
|
||||
: SynModuleDecl option * SynModuleDecl
|
||||
=
|
||||
let fields =
|
||||
interfaceType.Members
|
||||
|> List.map (constructMember spec interfaceType.Generics)
|
||||
|> List.map (constructMember spec)
|
||||
|> List.append (
|
||||
interfaceType.Properties
|
||||
|> List.map constructProperty
|
||||
@@ -214,8 +224,9 @@ module internal CapturingInterfaceMockGenerator =
|
||||
| None -> failwith $"unexpectedly got a field with no identifier: %O{f}"
|
||||
| Some idOpt -> idOpt.idText
|
||||
|
||||
f, extraType, fieldName
|
||||
fieldName, (f, extraType)
|
||||
)
|
||||
|> Map.ofList
|
||||
|
||||
let failwithNotImplemented (fieldName : string) =
|
||||
let failString = SynExpr.CreateConst $"Unimplemented mock function: %s{fieldName}"
|
||||
@@ -248,24 +259,16 @@ module internal CapturingInterfaceMockGenerator =
|
||||
|
||||
let originalMembers =
|
||||
fields
|
||||
|> List.map (fun (_, _, fieldName) -> SynLongIdent.createS fieldName, failwithNotImplemented fieldName)
|
||||
|> Map.toList
|
||||
|> List.map (fun (fieldName, _) -> SynLongIdent.createS fieldName, failwithNotImplemented fieldName)
|
||||
|
||||
let callsArrays =
|
||||
fields
|
||||
|> List.map (fun (_field, extraType, fieldName) ->
|
||||
let name = SynLongIdent.createS $"{fieldName}_Calls"
|
||||
let callsObject =
|
||||
SynLongIdent.createS "Calls",
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ $"%s{name}Calls" ; "Calls" ; "Empty" ])
|
||||
(SynExpr.CreateConst ())
|
||||
|
||||
let init =
|
||||
match extraType with
|
||||
| CallField.Original _ ->
|
||||
SynExpr.createIdent "ResizeArray" |> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
| CallField.ArgsObject _ ->
|
||||
SynExpr.createIdent "ResizeArray" |> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
|
||||
name, init
|
||||
)
|
||||
|
||||
interfaceExtras @ originalMembers @ callsArrays
|
||||
callsObject :: interfaceExtras @ originalMembers
|
||||
|
||||
let staticMemberEmpty =
|
||||
SynBinding.basic
|
||||
@@ -294,37 +297,109 @@ module internal CapturingInterfaceMockGenerator =
|
||||
[]
|
||||
|
||||
let nonExtras =
|
||||
fields |> Map.toSeq |> Seq.map (fun (_, (field, _)) -> field) |> Seq.toList
|
||||
|
||||
let calls =
|
||||
let ty =
|
||||
match interfaceType.Generics with
|
||||
| None -> SynType.createLongIdent' [ $"%s{name}Calls" ; "Calls" ]
|
||||
| Some generics ->
|
||||
generics.TyparDecls
|
||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||
|> SynType.app' (SynType.createLongIdent' [ $"%s{name}Calls" ; "Calls" ])
|
||||
|
||||
{
|
||||
Attrs = []
|
||||
Ident = Ident.create "Calls" |> Some
|
||||
Type = ty
|
||||
}
|
||||
|> SynField.make
|
||||
|
||||
calls :: extras @ nonExtras
|
||||
|
||||
let access =
|
||||
match interfaceType.Accessibility, spec.IsInternal with
|
||||
| Some (SynAccess.Public _), true
|
||||
| None, true -> SynAccess.Internal range0
|
||||
| Some (SynAccess.Public _), false -> SynAccess.Public range0
|
||||
| None, false -> SynAccess.Public range0
|
||||
| Some (SynAccess.Internal _), _ -> SynAccess.Internal range0
|
||||
| Some (SynAccess.Private _), _ -> SynAccess.Private range0
|
||||
|
||||
let accessAtLeastInternal =
|
||||
match access with
|
||||
| SynAccess.Private _ -> SynAccess.Internal range0
|
||||
| access -> access
|
||||
|
||||
let callsObject =
|
||||
let fields' =
|
||||
fields
|
||||
|> List.collect (fun (field, callType, fieldName) ->
|
||||
let callField =
|
||||
match callType with
|
||||
| CallField.Original ty ->
|
||||
{
|
||||
Attrs = []
|
||||
Ident = Some (fieldName + "_Calls" |> Ident.create)
|
||||
Type = SynType.app "ResizeArray" [ ty ]
|
||||
}
|
||||
|> SynField.make
|
||||
| CallField.ArgsObject (name, _, generics) ->
|
||||
{
|
||||
Attrs = []
|
||||
Ident = Some (fieldName + "_Calls" |> Ident.create)
|
||||
Type =
|
||||
match generics with
|
||||
| None -> SynType.named name.idText
|
||||
| Some generics ->
|
||||
generics.TyparDecls
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||
|> SynType.app name.idText
|
||||
|> List.singleton
|
||||
|> SynType.app "ResizeArray"
|
||||
}
|
||||
|> SynField.make
|
||||
|
||||
[ field ; callField ]
|
||||
|> Map.toSeq
|
||||
|> Seq.map (fun (fieldName, (_, callType)) ->
|
||||
match callType with
|
||||
| CallField.Original ty ->
|
||||
{
|
||||
Attrs = []
|
||||
Ident = Some (fieldName |> Ident.create)
|
||||
Type = SynType.app "ResizeArray" [ ty ]
|
||||
}
|
||||
|> SynField.make
|
||||
| CallField.ArgsObject (argsObjectName, _, generics) ->
|
||||
{
|
||||
Attrs = []
|
||||
Ident = Some (fieldName |> Ident.create)
|
||||
Type =
|
||||
match generics with
|
||||
| None -> SynType.named argsObjectName.idText
|
||||
| Some generics ->
|
||||
generics.TyparDecls
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||
|> SynType.app' (SynType.createLongIdent' [ argsObjectName.idText ])
|
||||
|> List.singleton
|
||||
|> SynType.app "ResizeArray"
|
||||
}
|
||||
|> SynField.make
|
||||
)
|
||||
|> Seq.toList
|
||||
|
||||
extras @ nonExtras
|
||||
let emptyMember =
|
||||
let returnType =
|
||||
match interfaceType.Generics with
|
||||
| None -> SynType.named "Calls"
|
||||
| Some generics ->
|
||||
let generics =
|
||||
match generics with
|
||||
| SynTyparDecls.PostfixList (decls = decls)
|
||||
| SynTyparDecls.PrefixList (decls = decls) -> decls
|
||||
| SynTyparDecls.SinglePrefix (decl = decl) -> [ decl ]
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||
|
||||
SynType.app "Calls" generics
|
||||
|
||||
fields
|
||||
|> Map.toSeq
|
||||
|> Seq.map (fun (name, _) ->
|
||||
SynLongIdent.createS name,
|
||||
SynExpr.applyFunction (SynExpr.createIdent "ResizeArray") (SynExpr.CreateConst ())
|
||||
)
|
||||
|> Seq.toList
|
||||
|> SynExpr.createRecord None
|
||||
|> SynBinding.basic [ Ident.create "Empty" ] [ SynPat.unit ]
|
||||
|> SynBinding.withXmlDoc (PreXmlDoc.create "A fresh calls object which has not yet had any calls made.")
|
||||
|> SynBinding.withReturnAnnotation returnType
|
||||
|> SynMemberDefn.staticMember
|
||||
|
||||
{
|
||||
RecordType.Name = Ident.create "Calls"
|
||||
Fields = fields'
|
||||
Members = Some [ emptyMember ]
|
||||
XmlDoc = PreXmlDoc.create $"All the calls made to a %s{name} mock" |> Some
|
||||
Generics = interfaceType.Generics
|
||||
TypeAccessibility = Some accessAtLeastInternal
|
||||
ImplAccessibility = None
|
||||
Attributes = [ SynAttribute.requireQualifiedAccess ]
|
||||
}
|
||||
|> AstHelper.defineRecordType
|
||||
|
||||
let interfaceMembers =
|
||||
let members =
|
||||
@@ -348,28 +423,65 @@ module internal CapturingInterfaceMockGenerator =
|
||||
|> fun i -> if tupledArgs.HasParen then SynPat.paren i else i
|
||||
)
|
||||
|
||||
let body =
|
||||
let tuples =
|
||||
let body, addToCalls =
|
||||
let tupleContents =
|
||||
memberInfo.Args
|
||||
|> List.mapi (fun i args ->
|
||||
args.Args
|
||||
|> List.mapi (fun j arg ->
|
||||
match arg.Type with
|
||||
| UnitType -> SynExpr.CreateConst ()
|
||||
| _ -> SynExpr.createIdent $"arg_%i{i}_%i{j}"
|
||||
| UnitType -> SynExpr.CreateConst (), arg.Id
|
||||
| _ -> SynExpr.createIdent $"arg_%i{i}_%i{j}", arg.Id
|
||||
)
|
||||
|> SynExpr.tuple
|
||||
)
|
||||
|
||||
let tuples = tupleContents |> List.map (List.map fst >> SynExpr.tuple)
|
||||
|
||||
match tuples |> List.rev with
|
||||
| [] -> failwith "expected args but got none"
|
||||
| last :: rest ->
|
||||
|
||||
(last, rest)
|
||||
||> List.fold SynExpr.applyTo
|
||||
|> SynExpr.applyFunction (
|
||||
SynExpr.createLongIdent' [ Ident.create "this" ; memberInfo.Identifier ]
|
||||
)
|
||||
let tuples = (last, rest) ||> List.fold SynExpr.applyTo
|
||||
|
||||
let body =
|
||||
tuples
|
||||
|> SynExpr.applyFunction (
|
||||
SynExpr.createLongIdent' [ Ident.create "this" ; memberInfo.Identifier ]
|
||||
)
|
||||
|
||||
let addToCalls =
|
||||
match Map.tryFind memberInfo.Identifier.idText fields with
|
||||
| None ->
|
||||
failwith
|
||||
$"unexpectedly looking up a nonexistent field %s{memberInfo.Identifier.idText}"
|
||||
| Some (_, result) ->
|
||||
match result with
|
||||
| CallField.Original _ -> tuples
|
||||
| CallField.ArgsObject _ ->
|
||||
tupleContents
|
||||
|> List.mapi (fun i fields ->
|
||||
match fields with
|
||||
| [ contents, Some ident ] -> SynLongIdent.create [ ident ], contents
|
||||
| [ contents, None ] -> SynLongIdent.createS $"Arg%i{i}", contents
|
||||
| _ ->
|
||||
SynLongIdent.createS $"Arg%i{i}",
|
||||
SynExpr.tupleNoParen (fields |> List.map fst)
|
||||
)
|
||||
|> SynExpr.createRecord None
|
||||
|> SynExpr.applyFunction (
|
||||
SynExpr.createLongIdent [ "this" ; "Calls" ; memberInfo.Identifier.idText ; "Add" ]
|
||||
)
|
||||
|> SynExpr.createLambda "_"
|
||||
|> SynExpr.applyFunction (
|
||||
SynExpr.createIdent "lock"
|
||||
|> SynExpr.applyTo (
|
||||
SynExpr.createLongIdent [ "this" ; "Calls" ; memberInfo.Identifier.idText ]
|
||||
)
|
||||
)
|
||||
|
||||
body, addToCalls
|
||||
|
||||
let body = [ addToCalls ; body ] |> SynExpr.sequential
|
||||
|
||||
SynBinding.basic [ Ident.create "this" ; memberInfo.Identifier ] headArgs body
|
||||
|> SynMemberDefn.memberImplementation
|
||||
@@ -401,15 +513,6 @@ module internal CapturingInterfaceMockGenerator =
|
||||
|
||||
SynMemberDefn.Interface (interfaceName, Some range0, Some (members @ properties), range0)
|
||||
|
||||
let access =
|
||||
match interfaceType.Accessibility, spec.IsInternal with
|
||||
| Some (SynAccess.Public _), true
|
||||
| None, true -> SynAccess.Internal range0
|
||||
| Some (SynAccess.Public _), false -> SynAccess.Public range0
|
||||
| None, false -> SynAccess.Public range0
|
||||
| Some (SynAccess.Internal _), _ -> SynAccess.Internal range0
|
||||
| Some (SynAccess.Private _), _ -> SynAccess.Private range0
|
||||
|
||||
let extraInterfaces =
|
||||
inherits
|
||||
|> Seq.map (fun inheritance ->
|
||||
@@ -445,16 +548,26 @@ module internal CapturingInterfaceMockGenerator =
|
||||
|
||||
let typeDecl = AstHelper.defineRecordType record
|
||||
|
||||
SynModuleDecl.Types (
|
||||
[
|
||||
for _, field, _ in fields do
|
||||
let callsModule =
|
||||
let types =
|
||||
fields
|
||||
|> Map.toSeq
|
||||
|> Seq.choose (fun (_, (_, field)) ->
|
||||
match field with
|
||||
| CallField.Original _ -> ()
|
||||
| CallField.ArgsObject (_, callType, _) -> yield callType
|
||||
yield typeDecl
|
||||
],
|
||||
range0
|
||||
)
|
||||
| CallField.Original _ -> None
|
||||
| CallField.ArgsObject (_, callType, _) -> Some (SynModuleDecl.Types ([ callType ], range0))
|
||||
)
|
||||
|> Seq.toList
|
||||
|
||||
types @ [ SynModuleDecl.Types ([ callsObject ], range0) ]
|
||||
|> SynModuleDecl.nestedModule (
|
||||
SynComponentInfo.create (Ident.create $"%s{name}Calls")
|
||||
|> SynComponentInfo.withAccessibility accessAtLeastInternal
|
||||
|> SynComponentInfo.addAttributes [ SynAttribute.requireQualifiedAccess ]
|
||||
)
|
||||
|> Some
|
||||
|
||||
(callsModule, SynModuleDecl.Types ([ typeDecl ], range0))
|
||||
|
||||
let createRecord
|
||||
(namespaceId : LongIdent)
|
||||
@@ -476,9 +589,15 @@ module internal CapturingInterfaceMockGenerator =
|
||||
s
|
||||
|> fun s -> s + "Mock"
|
||||
|
||||
let typeDecl = createType spec name interfaceType docString
|
||||
let callsTypes, typeDecl = createType spec name interfaceType docString
|
||||
|
||||
[ yield! opens |> List.map SynModuleDecl.openAny ; yield typeDecl ]
|
||||
[
|
||||
yield! opens |> List.map SynModuleDecl.openAny
|
||||
match callsTypes with
|
||||
| None -> ()
|
||||
| Some c -> yield c
|
||||
yield typeDecl
|
||||
]
|
||||
|> SynModuleOrNamespace.createNamespace namespaceId
|
||||
|
||||
open Myriad.Core
|
||||
|
@@ -1,5 +1,7 @@
|
||||
WoofWare.Myriad.Plugins.ArgParserGenerator inherit obj, implements Myriad.Core.IMyriadGenerator
|
||||
WoofWare.Myriad.Plugins.ArgParserGenerator..ctor [constructor]: unit
|
||||
WoofWare.Myriad.Plugins.CapturingInterfaceMockGenerator inherit obj, implements Myriad.Core.IMyriadGenerator
|
||||
WoofWare.Myriad.Plugins.CapturingInterfaceMockGenerator..ctor [constructor]: unit
|
||||
WoofWare.Myriad.Plugins.CreateCatamorphismGenerator inherit obj, implements Myriad.Core.IMyriadGenerator
|
||||
WoofWare.Myriad.Plugins.CreateCatamorphismGenerator..ctor [constructor]: unit
|
||||
WoofWare.Myriad.Plugins.HttpClientGenerator inherit obj, implements Myriad.Core.IMyriadGenerator
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "8.0",
|
||||
"version": "8.1",
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/main$"
|
||||
],
|
||||
|
Reference in New Issue
Block a user