Compare commits

..

11 Commits

Author SHA1 Message Date
dependabot[bot]
30eb28d00a Bump WoofWare.Whippet.Fantomas from 0.6.3 to 0.6.4 (#440) 2025-10-20 11:13:03 +00:00
patrick-conscriptus[bot]
62e1cf2c46 Upgrade Nix flake and deps (#439)
* Automated commit

* Fix link

---------

Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-10-19 04:54:20 +00:00
dependabot[bot]
fa81119cec Bump Microsoft.NET.Test.Sdk from 17.14.1 to 18.0.0 (#434)
* Bump Microsoft.NET.Test.Sdk from 17.14.1 to 18.0.0

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump NUnit3TestAdapter from 5.0.0 to 5.2.0

---
updated-dependencies:
- dependency-name: NUnit3TestAdapter
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: NUnit3TestAdapter
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump WoofWare.Expect from 0.8.2 to 0.8.3

---
updated-dependencies:
- dependency-name: WoofWare.Expect
  dependency-version: 0.8.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ApiSurface from 5.0.1 to 5.0.2

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: ApiSurface
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump TypeEquality from 0.3.0 to 0.4.2

---
updated-dependencies:
- dependency-name: TypeEquality
  dependency-version: 0.4.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-10-13 17:39:07 +00:00
patrick-conscriptus[bot]
7907cefaee Automated commit (#433)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-10-12 01:29:47 +00:00
patrick-conscriptus[bot]
e83ec1f152 Automated commit (#432)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-10-05 01:31:29 +00:00
Patrick Stevens
9d8cef8fdc Switch to trusted publishing (#431) 2025-10-03 09:37:32 +00:00
Patrick Stevens
1721ad1ac0 Unconditional function for empty generating mock (#430) 2025-09-30 21:52:59 +00:00
dependabot[bot]
857bde0ba9 Bump Nerdbank.GitVersioning from 3.8.38-alpha to 3.8.118 (#428)
* Bump Nerdbank.GitVersioning from 3.8.38-alpha to 3.8.118

---
updated-dependencies:
- dependency-name: Nerdbank.GitVersioning
  dependency-version: 3.8.118
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-09-29 23:52:31 +01:00
patrick-conscriptus[bot]
d10f608941 Automated commit (#427)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-09-28 01:31:56 +00:00
patrick-conscriptus[bot]
46effedfc4 Automated commit (#426)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-09-21 01:31:20 +00:00
Patrick Stevens
1b85182b9d GenerateCapturingMock that captures calls made to it (#425) 2025-09-18 15:42:10 +01:00
18 changed files with 918 additions and 344 deletions

View File

@@ -9,10 +9,10 @@
] ]
}, },
"fsharp-analyzers": { "fsharp-analyzers": {
"version": "0.32.1", "version": "0.33.1",
"commands": [ "commands": [
"fsharp-analyzers" "fsharp-analyzers"
] ]
} }
} }
} }

View File

@@ -301,12 +301,17 @@ jobs:
- name: Identify `dotnet` - name: Identify `dotnet`
id: dotnet-identify id: dotnet-identify
run: nix develop --command bash -c 'echo "dotnet=$(which dotnet)" >> $GITHUB_OUTPUT' run: nix develop --command bash -c 'echo "dotnet=$(which dotnet)" >> $GITHUB_OUTPUT'
- name: Obtain NuGet key
uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544
id: login
with:
user: ${{ secrets.NUGET_USER }}
- name: Publish to NuGet - name: Publish to NuGet
id: publish-success id: publish-success
uses: G-Research/common-actions/publish-nuget@2b7dc49cb14f3344fbe6019c14a31165e258c059 uses: G-Research/common-actions/publish-nuget@2b7dc49cb14f3344fbe6019c14a31165e258c059
with: with:
package-name: WoofWare.Myriad.Plugins.Attributes package-name: WoofWare.Myriad.Plugins.Attributes
nuget-key: ${{ secrets.NUGET_API_KEY }} nuget-key: ${{ steps.login.outputs.NUGET_API_KEY }}
nupkg-dir: packed/ nupkg-dir: packed/
dotnet: ${{ steps.dotnet-identify.outputs.dotnet }} dotnet: ${{ steps.dotnet-identify.outputs.dotnet }}
@@ -334,12 +339,17 @@ jobs:
- name: Identify `dotnet` - name: Identify `dotnet`
id: dotnet-identify id: dotnet-identify
run: nix develop --command bash -c 'echo "dotnet=$(which dotnet)" >> $GITHUB_OUTPUT' run: nix develop --command bash -c 'echo "dotnet=$(which dotnet)" >> $GITHUB_OUTPUT'
- name: Obtain NuGet key
uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544
id: login
with:
user: ${{ secrets.NUGET_USER }}
- name: Publish to NuGet - name: Publish to NuGet
id: publish-success id: publish-success
uses: G-Research/common-actions/publish-nuget@2b7dc49cb14f3344fbe6019c14a31165e258c059 uses: G-Research/common-actions/publish-nuget@2b7dc49cb14f3344fbe6019c14a31165e258c059
with: with:
package-name: WoofWare.Myriad.Plugins package-name: WoofWare.Myriad.Plugins
nuget-key: ${{ secrets.NUGET_API_KEY }} nuget-key: ${{ steps.login.outputs.NUGET_API_KEY }}
nupkg-dir: packed/ nupkg-dir: packed/
dotnet: ${{ steps.dotnet-identify.outputs.dotnet }} dotnet: ${{ steps.dotnet-identify.outputs.dotnet }}

View File

@@ -44,7 +44,7 @@ git config blame.ignoreRevsFile .git-blame-ignore-revs
## Dependencies ## Dependencies
I try to keep this repository's dependencies as few as possible, because (for example) any consumer of the source generator will also consume this project via the attributes. I try to keep this repository's dependencies as few as possible, because (for example) any consumer of the source generator will also consume this project via the attributes.
When adding dependencies, you will need to `nix run .#fetchDeps` to obtain a new copy of [the dependency lockfile](./nix/deps.nix). When adding dependencies, you will need to `nix run .#fetchDeps` to obtain a new copy of [the dependency lockfile](./nix/deps.json).
## Branch strategy ## Branch strategy

View File

@@ -9,180 +9,285 @@ namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type internal PublicTypeMock = type internal PublicTypeMock =
{ {
Calls : PublicTypeMockCalls.Calls
Mem1 : string * int -> string list Mem1 : string * int -> string list
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it. Mem3 : int * System.Threading.CancellationToken option -> string
Mem2_Calls : ResizeArray<string>
Mem3 : int * option<System.Threading.CancellationToken> -> string
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PublicTypeMock = static member Empty () : PublicTypeMock =
{ {
Calls = PublicTypeMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3")) Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
Mem3_Calls = ResizeArray ()
} }
interface IPublicType with interface IPublicType with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (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 namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type public PublicTypeInternalFalseMock = type public PublicTypeInternalFalseMock =
{ {
Calls : PublicTypeInternalFalseMockCalls.Calls
Mem1 : string * int -> string list Mem1 : string * int -> string list
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it. Mem3 : int * System.Threading.CancellationToken option -> string
Mem2_Calls : ResizeArray<string>
Mem3 : int * option<System.Threading.CancellationToken> -> string
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PublicTypeInternalFalseMock = static member Empty () : PublicTypeInternalFalseMock =
{ {
Calls = PublicTypeInternalFalseMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3")) Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
Mem3_Calls = ResizeArray ()
} }
interface IPublicTypeInternalFalse with interface IPublicTypeInternalFalse with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (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 namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type internal InternalTypeMock = type internal InternalTypeMock =
{ {
Calls : InternalTypeMockCalls.Calls
Mem1 : string * int -> unit Mem1 : string * int -> unit
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<string>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : InternalTypeMock = static member Empty () : InternalTypeMock =
{ {
Calls = InternalTypeMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface InternalType with interface InternalType with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) 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 namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type private PrivateTypeMock = type private PrivateTypeMock =
{ {
Calls : PrivateTypeMockCalls.Calls
Mem1 : string * int -> unit Mem1 : string * int -> unit
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<string>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PrivateTypeMock = static member Empty () : PrivateTypeMock =
{ {
Calls = PrivateTypeMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface PrivateType with interface PrivateType with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) 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 namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type private PrivateTypeInternalFalseMock = type private PrivateTypeInternalFalseMock =
{ {
Calls : PrivateTypeInternalFalseMockCalls.Calls
Mem1 : string * int -> unit Mem1 : string * int -> unit
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<string>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PrivateTypeInternalFalseMock = static member Empty () : PrivateTypeInternalFalseMock =
{ {
Calls = PrivateTypeInternalFalseMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface PrivateTypeInternalFalse with interface PrivateTypeInternalFalse with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) 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 namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type internal VeryPublicTypeMock<'a, 'b> = type internal VeryPublicTypeMock<'a, 'b> =
{ {
Calls : VeryPublicTypeMockCalls.Calls<'a, 'b>
Mem1 : 'a -> 'b Mem1 : 'a -> 'b
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<'a>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty () : VeryPublicTypeMock<'a, 'b> = static member Empty () : VeryPublicTypeMock<'a, 'b> =
{ {
Calls = VeryPublicTypeMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem1_Calls = ResizeArray ()
} }
interface VeryPublicType<'a, 'b> with 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 namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
[<RequireQualifiedAccess>]
module internal CurriedMockCalls = module internal CurriedMockCalls =
/// A single call to the Mem1 method /// A single call to the Mem1 method
type internal Mem1Call<'a> = type internal Mem1Call<'a> =
@@ -226,84 +331,178 @@ module internal CurriedMockCalls =
Arg1 : 'a * int 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 /// Mock record type for an interface
type internal CurriedMock<'a> = type internal CurriedMock<'a> =
{ {
Calls : CurriedMockCalls.Calls<'a>
Mem1 : int -> 'a -> string Mem1 : int -> 'a -> string
Mem1_Calls : ResizeArray<CurriedMockCalls.Mem1Call<'a>>
Mem2 : int * string -> 'a -> string Mem2 : int * string -> 'a -> string
Mem2_Calls : ResizeArray<CurriedMockCalls.Mem2Call<'a>>
Mem3 : (int * string) -> 'a -> string Mem3 : (int * string) -> 'a -> string
Mem3_Calls : ResizeArray<CurriedMockCalls.Mem3Call<'a>>
Mem4 : (int * string) -> ('a * int) -> string Mem4 : (int * string) -> ('a * int) -> string
Mem4_Calls : ResizeArray<CurriedMockCalls.Mem4Call<'a>>
Mem5 : int * string -> ('a * int) -> string Mem5 : int * string -> ('a * int) -> string
Mem5_Calls : ResizeArray<CurriedMockCalls.Mem5Call<'a>>
Mem6 : int * string -> 'a * int -> string Mem6 : int * string -> 'a * int -> string
Mem6_Calls : ResizeArray<CurriedMockCalls.Mem6Call<'a>>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty () : CurriedMock<'a> = static member Empty () : CurriedMock<'a> =
{ {
Calls = CurriedMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3")) Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4")) Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4"))
Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5")) Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5"))
Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem6")) 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 interface Curried<'a> with
member this.Mem1 arg_0_0 arg_1_0 = this.Mem1 (arg_0_0) (arg_1_0) member 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) lock
member this.Mem3 arg_0_0 arg_1_0 = this.Mem3 (arg_0_0) (arg_1_0) 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)) = 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) 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)) = 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) 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) = 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) this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
namespace SomeNamespace.CapturingMock namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type internal TypeWithInterfaceMock = type internal TypeWithInterfaceMock =
{ {
Calls : TypeWithInterfaceMockCalls.Calls
/// Implementation of IDisposable.Dispose /// Implementation of IDisposable.Dispose
Dispose : unit -> unit Dispose : unit -> unit
Mem1 : string option -> string[] Async Mem1 : string option -> string[] Async
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string option>
Mem2 : unit -> string[] Async Mem2 : unit -> string[] Async
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<unit>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : TypeWithInterfaceMock = static member Empty () : TypeWithInterfaceMock =
{ {
Calls = TypeWithInterfaceMockCalls.Calls.Empty ()
Dispose = (fun () -> ()) Dispose = (fun () -> ())
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface TypeWithInterface with interface TypeWithInterface with
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0) member this.Mem1 arg_0_0 =
member this.Mem2 () = this.Mem2 (()) 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 interface System.IDisposable with
member this.Dispose () : unit = this.Dispose () member this.Dispose () : unit = this.Dispose ()
@@ -312,36 +511,50 @@ namespace SomeNamespace.CapturingMock
open System open System
open WoofWare.Myriad.Plugins 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 /// Mock record type for an interface
type internal TypeWithPropertiesMock = type internal TypeWithPropertiesMock =
{ {
Calls : TypeWithPropertiesMockCalls.Calls
/// Implementation of IDisposable.Dispose /// Implementation of IDisposable.Dispose
Dispose : unit -> unit Dispose : unit -> unit
Prop1 : unit -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Prop1_Calls : ResizeArray<unit>
Prop2 : unit -> unit Async
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Prop2_Calls : ResizeArray<unit>
Mem1 : string option -> string[] Async Mem1 : string option -> string[] Async
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it. Prop1 : unit -> int
Mem1_Calls : ResizeArray<string option> Prop2 : unit -> unit Async
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : TypeWithPropertiesMock = static member Empty () : TypeWithPropertiesMock =
{ {
Calls = TypeWithPropertiesMockCalls.Calls.Empty ()
Dispose = (fun () -> ()) Dispose = (fun () -> ())
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Prop1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop1")) Prop1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop1"))
Prop2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop2")) 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 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.Prop1 = this.Prop1 ()
member this.Prop2 = this.Prop2 () member this.Prop2 = this.Prop2 ()

View File

@@ -8,174 +8,279 @@ namespace SomeNamespace.CapturingMock
open System 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 /// Mock record type for an interface
type internal PublicTypeNoAttrMock = type internal PublicTypeNoAttrMock =
{ {
Calls : PublicTypeNoAttrMockCalls.Calls
Mem1 : string * int -> string list Mem1 : string * int -> string list
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it. Mem3 : int * System.Threading.CancellationToken option -> string
Mem2_Calls : ResizeArray<string>
Mem3 : int * option<System.Threading.CancellationToken> -> string
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PublicTypeNoAttrMock = static member Empty () : PublicTypeNoAttrMock =
{ {
Calls = PublicTypeNoAttrMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3")) Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
Mem3_Calls = ResizeArray ()
} }
interface IPublicTypeNoAttr with interface IPublicTypeNoAttr with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (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 namespace SomeNamespace.CapturingMock
open System 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 /// Mock record type for an interface
type public PublicTypeInternalFalseNoAttrMock = type public PublicTypeInternalFalseNoAttrMock =
{ {
Calls : PublicTypeInternalFalseNoAttrMockCalls.Calls
Mem1 : string * int -> string list Mem1 : string * int -> string list
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it. Mem3 : int * System.Threading.CancellationToken option -> string
Mem2_Calls : ResizeArray<string>
Mem3 : int * option<System.Threading.CancellationToken> -> string
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem3_Calls : ResizeArray<int * System.Threading.CancellationToken>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PublicTypeInternalFalseNoAttrMock = static member Empty () : PublicTypeInternalFalseNoAttrMock =
{ {
Calls = PublicTypeInternalFalseNoAttrMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3")) Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
Mem3_Calls = ResizeArray ()
} }
interface IPublicTypeInternalFalseNoAttr with interface IPublicTypeInternalFalseNoAttr with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) lock this.Calls.Mem1 (fun _ -> this.Calls.Mem1.Add (arg_0_0, arg_0_1))
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (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 namespace SomeNamespace.CapturingMock
open System 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 /// Mock record type for an interface
type internal InternalTypeNoAttrMock = type internal InternalTypeNoAttrMock =
{ {
Calls : InternalTypeNoAttrMockCalls.Calls
Mem1 : string * int -> unit Mem1 : string * int -> unit
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<string>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : InternalTypeNoAttrMock = static member Empty () : InternalTypeNoAttrMock =
{ {
Calls = InternalTypeNoAttrMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface InternalTypeNoAttr with interface InternalTypeNoAttr with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) 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 namespace SomeNamespace.CapturingMock
open System 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 /// Mock record type for an interface
type private PrivateTypeNoAttrMock = type private PrivateTypeNoAttrMock =
{ {
Calls : PrivateTypeNoAttrMockCalls.Calls
Mem1 : string * int -> unit Mem1 : string * int -> unit
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<string>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PrivateTypeNoAttrMock = static member Empty () : PrivateTypeNoAttrMock =
{ {
Calls = PrivateTypeNoAttrMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface PrivateTypeNoAttr with interface PrivateTypeNoAttr with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) 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 namespace SomeNamespace.CapturingMock
open System 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 /// Mock record type for an interface
type private PrivateTypeInternalFalseNoAttrMock = type private PrivateTypeInternalFalseNoAttrMock =
{ {
Calls : PrivateTypeInternalFalseNoAttrMockCalls.Calls
Mem1 : string * int -> unit Mem1 : string * int -> unit
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string * int>
Mem2 : string -> int Mem2 : string -> int
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<string>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : PrivateTypeInternalFalseNoAttrMock = static member Empty () : PrivateTypeInternalFalseNoAttrMock =
{ {
Calls = PrivateTypeInternalFalseNoAttrMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface PrivateTypeInternalFalseNoAttr with interface PrivateTypeInternalFalseNoAttr with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) =
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) 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 namespace SomeNamespace.CapturingMock
open System 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 /// Mock record type for an interface
type internal VeryPublicTypeNoAttrMock<'a, 'b> = type internal VeryPublicTypeNoAttrMock<'a, 'b> =
{ {
Calls : VeryPublicTypeNoAttrMockCalls.Calls<'a, 'b>
Mem1 : 'a -> 'b Mem1 : 'a -> 'b
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<'a>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty () : VeryPublicTypeNoAttrMock<'a, 'b> = static member Empty () : VeryPublicTypeNoAttrMock<'a, 'b> =
{ {
Calls = VeryPublicTypeNoAttrMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem1_Calls = ResizeArray ()
} }
interface VeryPublicTypeNoAttr<'a, 'b> with 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 namespace SomeNamespace.CapturingMock
open System open System
[<RequireQualifiedAccess>]
module internal CurriedNoAttrMockCalls = module internal CurriedNoAttrMockCalls =
/// A single call to the Mem1 method /// A single call to the Mem1 method
type internal Mem1Call<'a> = type internal Mem1Call<'a> =
@@ -219,83 +324,177 @@ module internal CurriedNoAttrMockCalls =
Arg1 : 'a * int 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 /// Mock record type for an interface
type internal CurriedNoAttrMock<'a> = type internal CurriedNoAttrMock<'a> =
{ {
Calls : CurriedNoAttrMockCalls.Calls<'a>
Mem1 : int -> 'a -> string Mem1 : int -> 'a -> string
Mem1_Calls : ResizeArray<CurriedNoAttrMockCalls.Mem1Call<'a>>
Mem2 : int * string -> 'a -> string Mem2 : int * string -> 'a -> string
Mem2_Calls : ResizeArray<CurriedNoAttrMockCalls.Mem2Call<'a>>
Mem3 : (int * string) -> 'a -> string Mem3 : (int * string) -> 'a -> string
Mem3_Calls : ResizeArray<CurriedNoAttrMockCalls.Mem3Call<'a>>
Mem4 : (int * string) -> ('a * int) -> string Mem4 : (int * string) -> ('a * int) -> string
Mem4_Calls : ResizeArray<CurriedNoAttrMockCalls.Mem4Call<'a>>
Mem5 : int * string -> ('a * int) -> string Mem5 : int * string -> ('a * int) -> string
Mem5_Calls : ResizeArray<CurriedNoAttrMockCalls.Mem5Call<'a>>
Mem6 : int * string -> 'a * int -> string Mem6 : int * string -> 'a * int -> string
Mem6_Calls : ResizeArray<CurriedNoAttrMockCalls.Mem6Call<'a>>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty () : CurriedNoAttrMock<'a> = static member Empty () : CurriedNoAttrMock<'a> =
{ {
Calls = CurriedNoAttrMockCalls.Calls.Empty ()
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3")) Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4")) Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4"))
Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5")) Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5"))
Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem6")) 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 interface CurriedNoAttr<'a> with
member this.Mem1 arg_0_0 arg_1_0 = this.Mem1 (arg_0_0) (arg_1_0) member 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) lock
member this.Mem3 ((arg_0_0, arg_0_1)) arg_1_0 = this.Mem3 (arg_0_0, arg_0_1) (arg_1_0) 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)) = 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) 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)) = 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) 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) = 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) this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
namespace SomeNamespace.CapturingMock namespace SomeNamespace.CapturingMock
open System 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 /// Mock record type for an interface
type internal TypeWithInterfaceNoAttrMock = type internal TypeWithInterfaceNoAttrMock =
{ {
Calls : TypeWithInterfaceNoAttrMockCalls.Calls
/// Implementation of IDisposable.Dispose /// Implementation of IDisposable.Dispose
Dispose : unit -> unit Dispose : unit -> unit
Mem1 : string option -> string[] Async Mem1 : string option -> string[] Async
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem1_Calls : ResizeArray<string option>
Mem2 : unit -> string[] Async Mem2 : unit -> string[] Async
/// Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it.
Mem2_Calls : ResizeArray<unit>
} }
/// An implementation where every non-unit method throws. /// An implementation where every non-unit method throws.
static member Empty : TypeWithInterfaceNoAttrMock = static member Empty () : TypeWithInterfaceNoAttrMock =
{ {
Calls = TypeWithInterfaceNoAttrMockCalls.Calls.Empty ()
Dispose = (fun () -> ()) Dispose = (fun () -> ())
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1")) Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2")) Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
Mem1_Calls = ResizeArray ()
Mem2_Calls = ResizeArray ()
} }
interface TypeWithInterfaceNoAttr with interface TypeWithInterfaceNoAttr with
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0) member this.Mem1 arg_0_0 =
member this.Mem2 () = this.Mem2 (()) 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 interface System.IDisposable with
member this.Dispose () : unit = this.Dispose () member this.Dispose () : unit = this.Dispose ()

View File

@@ -10,7 +10,7 @@
<WarnOn>FS3388,FS3559</WarnOn> <WarnOn>FS3388,FS3559</WarnOn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="3.8.38-alpha" PrivateAssets="all" /> <PackageReference Include="Nerdbank.GitVersioning" Version="3.8.118" PrivateAssets="all" />
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com" /> <SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''"> <PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">

View File

@@ -478,40 +478,51 @@ It takes a type like this:
```fsharp ```fsharp
[<GenerateCapturingMock>] [<GenerateCapturingMock>]
type IPublicType = type IPublicType =
abstract Mem1 : string * int -> string list abstract Mem1 : string * int -> thing : bool -> string list
abstract Mem2 : baz : string -> unit -> int abstract Mem2 : baz : string -> unit -> int
``` ```
and stamps out types like this: and stamps out types like this:
```fsharp ```fsharp
[<RequireQualifiedAccess>]
module internal PublicTypeCalls = module internal PublicTypeCalls =
type internal Mem2Call = type internal Mem1Call =
{ {
baz : string Arg0 : string * int
Arg1 : unit thing : bool
} }
type internal Calls =
{
Mem1 : ResizeArray<Mem1Call>
Mem2 : ResizeArray<string>
}
static member Empty () = { Mem1 = ResizeArray () ; Mem2 = ResizeArray () }
/// Mock record type for an interface /// Mock record type for an interface
type internal PublicTypeMock = type internal PublicTypeMock =
{ {
Mem1 : string * int -> string list Mem1 : string * int -> bool -> string list
Mem2 : string -> int Mem2 : string -> int
Mem2_Calls : ResizeArray<string * int> Calls : PublicTypeCalls.Calls
Mem2_Calls : ResizeArray<PublicTypeCalls.Mem2Call>
} }
static member Empty : PublicTypeMock = static member Empty : PublicTypeMock =
{ {
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
Mem1_Calls = ResizeArray () Calls = PublicTypeMockCalls.Calls.Empty ()
Mem2_Calls = ResizeArray ()
} }
interface IPublicType with interface IPublicType with
member this.Mem1 (arg0, arg1) = this.Mem1 (arg0, arg1) member this.Mem1 (arg0, arg1) =
member this.Mem2 (arg0) = this.Mem2 (arg0) 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? ### What's the point?
@@ -525,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>]`. * 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` ## `CreateCatamorphism`
Takes a collection of mutually recursive discriminated unions: Takes a collection of mutually recursive discriminated unions:
@@ -611,13 +652,13 @@ For example, [PureGymDto.fs](./ConsumePlugin/PureGymDto.fs) is a real-world set
* In your `.fsproj` file, define a helper variable so that subsequent steps don't all have to be kept in sync: * In your `.fsproj` file, define a helper variable so that subsequent steps don't all have to be kept in sync:
```xml ```xml
<PropertyGroup> <PropertyGroup>
<WoofWareMyriadPluginVersion>2.0.1</WoofWareMyriadPluginVersion> <WoofWareMyriadPluginVersion>9.0.1</WoofWareMyriadPluginVersion>
</PropertyGroup> </PropertyGroup>
``` ```
* Take a reference on `WoofWare.Myriad.Plugins.Attributes` (which has no other dependencies), to obtain access to the attributes which the generator will recognise: * Take a reference on `WoofWare.Myriad.Plugins.Attributes` (which has no other dependencies), to obtain access to the attributes which the generator will recognise:
```xml ```xml
<ItemGroup> <ItemGroup>
<PackageReference Include="WoofWare.Myriad.Plugins.Attributes" Version="2.0.2" /> <PackageReference Include="WoofWare.Myriad.Plugins.Attributes" Version="3.7.2" />
</ItemGroup> </ItemGroup>
``` ```
* Take a reference (with private assets, to prevent these from propagating to your own assembly) on `WoofWare.Myriad.Plugins`, to obtain the plugins which Myriad will run, and on `Myriad.Sdk`, to obtain the Myriad binary itself: * Take a reference (with private assets, to prevent these from propagating to your own assembly) on `WoofWare.Myriad.Plugins`, to obtain the plugins which Myriad will run, and on `Myriad.Sdk`, to obtain the Myriad binary itself:

View File

@@ -32,7 +32,11 @@ type GenerateMockAttribute (isInternal : bool) =
/// record update syntax to easily specify partially-implemented mock objects. /// 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. /// 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) = type GenerateCapturingMockAttribute (isInternal : bool) =
inherit Attribute () inherit Attribute ()
/// The default value of `isInternal`, the optional argument to the GenerateCapturingMockAttribute constructor. /// The default value of `isInternal`, the optional argument to the GenerateCapturingMockAttribute constructor.

View File

@@ -17,10 +17,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ApiSurface" Version="5.0.1" /> <PackageReference Include="ApiSurface" Version="5.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0"/>
<PackageReference Include="NUnit" Version="4.3.2"/> <PackageReference Include="NUnit" Version="4.3.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"/> <PackageReference Include="NUnit3TestAdapter" Version="5.2.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -11,7 +11,7 @@ module TestCapturingMockGenerator =
[<Test>] [<Test>]
let ``Example of use: IPublicType`` () = let ``Example of use: IPublicType`` () =
let mock : IPublicType = let mock : IPublicType =
{ PublicTypeMock.Empty with { PublicTypeMock.Empty () with
Mem1 = fun (s, count) -> List.replicate count s Mem1 = fun (s, count) -> List.replicate count s
} }
:> _ :> _
@@ -38,7 +38,7 @@ module TestCapturingMockGenerator =
[<Test>] [<Test>]
let ``Example of use: properties`` () = let ``Example of use: properties`` () =
let mock : TypeWithProperties = let mock : TypeWithProperties =
{ TypeWithPropertiesMock.Empty with { TypeWithPropertiesMock.Empty () with
Mem1 = fun i -> async { return Option.toArray i } Mem1 = fun i -> async { return Option.toArray i }
Prop1 = fun () -> 44 Prop1 = fun () -> 44
} }
@@ -50,7 +50,7 @@ module TestCapturingMockGenerator =
[<Test>] [<Test>]
let ``Example of curried use`` () = let ``Example of curried use`` () =
let mock = let mock' =
{ CurriedMock<string>.Empty () with { CurriedMock<string>.Empty () with
Mem1 = Mem1 =
fun x y -> fun x y ->
@@ -59,9 +59,11 @@ module TestCapturingMockGenerator =
"it's me" "it's me"
} }
let mock = mock' :> Curried<_>
mock.Mem1 3 "hello" |> shouldEqual "it's me" mock.Mem1 3 "hello" |> shouldEqual "it's me"
lock mock.Mem1_Calls (fun () -> Seq.toList mock.Mem1_Calls) lock mock'.Calls.Mem1 (fun () -> Seq.toList mock'.Calls.Mem1)
|> List.exactlyOne |> List.exactlyOne
|> shouldEqual |> shouldEqual
{ {

View File

@@ -11,7 +11,7 @@ module TestCapturingMockGeneratorNoAttr =
[<Test>] [<Test>]
let ``Example of use: IPublicType`` () = let ``Example of use: IPublicType`` () =
let mock : IPublicTypeNoAttr = let mock : IPublicTypeNoAttr =
{ PublicTypeNoAttrMock.Empty with { PublicTypeNoAttrMock.Empty () with
Mem1 = fun (s, count) -> List.replicate count s Mem1 = fun (s, count) -> List.replicate count s
} }
:> _ :> _

View File

@@ -55,13 +55,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ApiSurface" Version="5.0.1" /> <PackageReference Include="ApiSurface" Version="5.0.2" />
<PackageReference Include="FsCheck" Version="3.3.1" /> <PackageReference Include="FsCheck" Version="3.3.1" />
<PackageReference Include="FsUnit" Version="7.1.1" /> <PackageReference Include="FsUnit" Version="7.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageReference Include="NUnit" Version="4.3.2" /> <PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" /> <PackageReference Include="NUnit3TestAdapter" Version="5.2.0" />
<PackageReference Include="WoofWare.Expect" Version="0.8.2" /> <PackageReference Include="WoofWare.Expect" Version="0.8.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -50,7 +50,12 @@ module internal CapturingInterfaceMockGenerator =
Attrs = [] Attrs = []
Type = Type =
tupledArg.Args 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 |> SynType.tupleNoParen
|> Option.get |> Option.get
} }
@@ -75,7 +80,7 @@ module internal CapturingInterfaceMockGenerator =
let private buildType (x : ParameterInfo) : SynType = let private buildType (x : ParameterInfo) : SynType =
if x.IsOptional then if x.IsOptional then
SynType.app "option" [ x.Type ] SynType.appPostfix "option" x.Type
else else
x.Type x.Type
@@ -139,7 +144,12 @@ module internal CapturingInterfaceMockGenerator =
| [] -> failwith "expected args in member" | [] -> failwith "expected args in member"
| [ ty ] -> | [ ty ] ->
ty.Args ty.Args
|> List.map _.Type |> List.map (fun pi ->
if pi.IsOptional then
SynType.appPostfix "option" pi.Type
else
pi.Type
)
|> SynType.tupleNoParen |> SynType.tupleNoParen
|> Option.get |> Option.get
|> CallField.Original |> CallField.Original
@@ -214,8 +224,9 @@ module internal CapturingInterfaceMockGenerator =
| None -> failwith $"unexpectedly got a field with no identifier: %O{f}" | None -> failwith $"unexpectedly got a field with no identifier: %O{f}"
| Some idOpt -> idOpt.idText | Some idOpt -> idOpt.idText
f, extraType, fieldName fieldName, (f, extraType)
) )
|> Map.ofList
let failwithNotImplemented (fieldName : string) = let failwithNotImplemented (fieldName : string) =
let failString = SynExpr.CreateConst $"Unimplemented mock function: %s{fieldName}" let failString = SynExpr.CreateConst $"Unimplemented mock function: %s{fieldName}"
@@ -248,28 +259,21 @@ module internal CapturingInterfaceMockGenerator =
let originalMembers = let originalMembers =
fields fields
|> List.map (fun (_, _, fieldName) -> SynLongIdent.createS fieldName, failwithNotImplemented fieldName) |> Map.toList
|> List.map (fun (fieldName, _) -> SynLongIdent.createS fieldName, failwithNotImplemented fieldName)
let callsArrays = let callsObject =
fields SynLongIdent.createS "Calls",
|> List.map (fun (_field, _, fieldName) -> SynExpr.applyFunction
let name = SynLongIdent.createS $"%s{fieldName}_Calls" (SynExpr.createLongIdent [ $"%s{name}Calls" ; "Calls" ; "Empty" ])
(SynExpr.CreateConst ())
let init = callsObject :: interfaceExtras @ originalMembers
SynExpr.createIdent "ResizeArray" |> SynExpr.applyTo (SynExpr.CreateConst ())
name, init
)
interfaceExtras @ originalMembers @ callsArrays
let staticMemberEmpty = let staticMemberEmpty =
SynBinding.basic SynBinding.basic
[ Ident.create "Empty" ] [ Ident.create "Empty" ]
(if interfaceType.Generics.IsNone then [ SynPat.unit ]
[]
else
[ SynPat.unit ])
(SynExpr.createRecord None emptyRecordFieldInstantiations) (SynExpr.createRecord None emptyRecordFieldInstantiations)
|> SynBinding.withXmlDoc (PreXmlDoc.create "An implementation where every non-unit method throws.") |> SynBinding.withXmlDoc (PreXmlDoc.create "An implementation where every non-unit method throws.")
|> SynBinding.withReturnAnnotation constructorReturnType |> SynBinding.withReturnAnnotation constructorReturnType
@@ -290,43 +294,109 @@ module internal CapturingInterfaceMockGenerator =
[] []
let nonExtras = 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 fields
|> List.collect (fun (field, callType, fieldName) -> |> Map.toSeq
let callField = |> Seq.map (fun (fieldName, (_, callType)) ->
match callType with match callType with
| CallField.Original ty -> | CallField.Original ty ->
{ {
Attrs = [] Attrs = []
Ident = Some (fieldName + "_Calls" |> Ident.create) Ident = Some (fieldName |> Ident.create)
Type = SynType.app "ResizeArray" [ ty ] Type = SynType.app "ResizeArray" [ ty ]
} }
|> SynField.make |> SynField.make
|> SynField.withDocString ( | CallField.ArgsObject (argsObjectName, _, generics) ->
PreXmlDoc.create {
"Additions to this ResizeArray are locked on itself. For maximum safety, lock on this field before reading it." Attrs = []
) Ident = Some (fieldName |> Ident.create)
| CallField.ArgsObject (argsObjectName, _, generics) -> Type =
{ match generics with
Attrs = [] | None -> SynType.named argsObjectName.idText
Ident = Some (fieldName + "_Calls" |> Ident.create) | Some generics ->
Type = generics.TyparDecls
match generics with |> List.map (fun (SynTyparDecl.SynTyparDecl (_, typar)) -> SynType.var typar)
| None -> SynType.named argsObjectName.idText |> SynType.app' (SynType.createLongIdent' [ argsObjectName.idText ])
| Some generics -> |> List.singleton
generics.TyparDecls |> SynType.app "ResizeArray"
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, typar)) -> SynType.var typar) }
|> SynType.app' ( |> SynField.make
SynType.createLongIdent' [ $"%s{name}Calls" ; argsObjectName.idText ]
)
|> List.singleton
|> SynType.app "ResizeArray"
}
|> SynField.make
[ field ; callField ]
) )
|> 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 interfaceMembers =
let members = let members =
@@ -350,28 +420,65 @@ module internal CapturingInterfaceMockGenerator =
|> fun i -> if tupledArgs.HasParen then SynPat.paren i else i |> fun i -> if tupledArgs.HasParen then SynPat.paren i else i
) )
let body = let body, addToCalls =
let tuples = let tupleContents =
memberInfo.Args memberInfo.Args
|> List.mapi (fun i args -> |> List.mapi (fun i args ->
args.Args args.Args
|> List.mapi (fun j arg -> |> List.mapi (fun j arg ->
match arg.Type with match arg.Type with
| UnitType -> SynExpr.CreateConst () | UnitType -> SynExpr.CreateConst (), arg.Id
| _ -> SynExpr.createIdent $"arg_%i{i}_%i{j}" | _ -> 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 match tuples |> List.rev with
| [] -> failwith "expected args but got none" | [] -> failwith "expected args but got none"
| last :: rest -> | last :: rest ->
(last, rest) let tuples = (last, rest) ||> List.fold SynExpr.applyTo
||> List.fold SynExpr.applyTo
|> SynExpr.applyFunction ( let body =
SynExpr.createLongIdent' [ Ident.create "this" ; memberInfo.Identifier ] 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 SynBinding.basic [ Ident.create "this" ; memberInfo.Identifier ] headArgs body
|> SynMemberDefn.memberImplementation |> SynMemberDefn.memberImplementation
@@ -403,15 +510,6 @@ module internal CapturingInterfaceMockGenerator =
SynMemberDefn.Interface (interfaceName, Some range0, Some (members @ properties), range0) 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 = let extraInterfaces =
inherits inherits
|> Seq.map (fun inheritance -> |> Seq.map (fun inheritance ->
@@ -448,22 +546,23 @@ module internal CapturingInterfaceMockGenerator =
let typeDecl = AstHelper.defineRecordType record let typeDecl = AstHelper.defineRecordType record
let callsModule = let callsModule =
fields let types =
|> List.choose (fun (_, field, _) -> fields
match field with |> Map.toSeq
| CallField.Original _ -> None |> Seq.choose (fun (_, (_, field)) ->
| CallField.ArgsObject (_, callType, _) -> Some callType match field with
| 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 ]
) )
|> function |> Some
| [] -> None
| l ->
SynModuleDecl.Types (l, range0)
|> List.singleton
|> SynModuleDecl.nestedModule (
SynComponentInfo.create (Ident.create $"%s{name}Calls")
|> SynComponentInfo.withAccessibility access
)
|> Some
(callsModule, SynModuleDecl.Types ([ typeDecl ], range0)) (callsModule, SynModuleDecl.Types ([ typeDecl ], range0))

View File

@@ -21,8 +21,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Myriad.Core" Version="0.8.3" /> <PackageReference Include="Myriad.Core" Version="0.8.3" />
<PackageReference Include="TypeEquality" Version="0.3.0" /> <PackageReference Include="TypeEquality" Version="0.4.2" />
<PackageReference Include="WoofWare.Whippet.Fantomas" Version="0.6.3" /> <PackageReference Include="WoofWare.Whippet.Fantomas" Version="0.6.4" />
<!-- the lowest version allowed by Myriad.Core --> <!-- the lowest version allowed by Myriad.Core -->
<PackageReference Update="FSharp.Core" Version="6.0.1" PrivateAssets="all"/> <PackageReference Update="FSharp.Core" Version="6.0.1" PrivateAssets="all"/>
</ItemGroup> </ItemGroup>

View File

@@ -1,5 +1,5 @@
{ {
"version": "8.1", "version": "9.0",
"publicReleaseRefSpec": [ "publicReleaseRefSpec": [
"^refs/heads/main$" "^refs/heads/main$"
], ],
@@ -11,4 +11,4 @@
":/README.md", ":/README.md",
":/Directory.Build.props" ":/Directory.Build.props"
] ]
} }

View File

@@ -10,7 +10,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.17.0]" /> <PackageDownload Include="WoofWare.FSharpAnalyzers" Version="[0.2.1]" />
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.19.0]" />
</ItemGroup> </ItemGroup>
</Project> </Project>

6
flake.lock generated
View File

@@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1757746433, "lastModified": 1760596604,
"narHash": "sha256-fEvTiU4s9lWgW7mYEU/1QUPirgkn+odUBTaindgiziY=", "narHash": "sha256-J/i5K6AAz/y5dBePHQOuzC7MbhyTOKsd/GLezSbEFiM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6d7ec06d6868ac6d94c371458fc2391ded9ff13d", "rev": "3cbe716e2346710d6e1f7c559363d14e11c32a43",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -1,8 +1,8 @@
[ [
{ {
"pname": "ApiSurface", "pname": "ApiSurface",
"version": "5.0.1", "version": "5.0.2",
"hash": "sha256-0GMXEMFgWbbE2OGxW+6h4zGgQHg+IZy1aI13Dn97xSU=" "hash": "sha256-zcq1H1ccQzsZQf4kolzoOBSbyz07skihgPAvQ9Jri+E="
}, },
{ {
"pname": "fantomas", "pname": "fantomas",
@@ -31,8 +31,8 @@
}, },
{ {
"pname": "fsharp-analyzers", "pname": "fsharp-analyzers",
"version": "0.32.1", "version": "0.33.1",
"hash": "sha256-le6rPnAF7cKGBZ2w8H2u9glK+6rT2ZjiAVnrkH2IhrM=" "hash": "sha256-vYXvqnf3en487svFv3CmNl24SolwMYzu6zKKGXNxSu8="
}, },
{ {
"pname": "FSharp.Core", "pname": "FSharp.Core",
@@ -61,8 +61,8 @@
}, },
{ {
"pname": "Microsoft.ApplicationInsights", "pname": "Microsoft.ApplicationInsights",
"version": "2.22.0", "version": "2.23.0",
"hash": "sha256-mUQ63atpT00r49ca50uZu2YCiLg3yd6r3HzTryqcuEA=" "hash": "sha256-5sf3bg7CZZjHseK+F3foOchEhmVeioePxMZVvS6Rjb0="
}, },
{ {
"pname": "Microsoft.AspNetCore.App.Ref", "pname": "Microsoft.AspNetCore.App.Ref",
@@ -91,13 +91,13 @@
}, },
{ {
"pname": "Microsoft.CodeCoverage", "pname": "Microsoft.CodeCoverage",
"version": "17.14.1", "version": "18.0.0",
"hash": "sha256-f8QytG8GvRoP47rO2KEmnDLxIpyesaq26TFjDdW40Gs=" "hash": "sha256-1RNxheCYASMusDC48BXtaO3MhnInw15JVfjfLM1VMGA="
}, },
{ {
"pname": "Microsoft.NET.Test.Sdk", "pname": "Microsoft.NET.Test.Sdk",
"version": "17.14.1", "version": "18.0.0",
"hash": "sha256-mZUzDFvFp7x1nKrcnRd0hhbNu5g8EQYt8SKnRgdhT/A=" "hash": "sha256-9iW+9mvMeZgDXwSoR08bnvRNsN4jT8OVWcjq3lcE+cs="
}, },
{ {
"pname": "Microsoft.NETCore.App.Host.linux-arm64", "pname": "Microsoft.NETCore.App.Host.linux-arm64",
@@ -166,43 +166,48 @@
}, },
{ {
"pname": "Microsoft.Testing.Extensions.Telemetry", "pname": "Microsoft.Testing.Extensions.Telemetry",
"version": "1.5.3", "version": "1.9.0",
"hash": "sha256-bIXwPSa3jkr2b6xINOqMUs6/uj/r4oVFM7xq3uVIZDU=" "hash": "sha256-JT91ThKLEyoRS/8ZJqZwlSTT7ofC2QhNqPFI3pYmMaw="
}, },
{ {
"pname": "Microsoft.Testing.Extensions.TrxReport.Abstractions", "pname": "Microsoft.Testing.Extensions.TrxReport.Abstractions",
"version": "1.5.3", "version": "1.9.0",
"hash": "sha256-IfMRfcyaIKEMRtx326ICKtinDBEfGw/Sv8ZHawJ96Yc=" "hash": "sha256-oscZOEKw7gM6eRdDrOS3x+CwqIvXWRmfmi0ugCxBRw0="
}, },
{ {
"pname": "Microsoft.Testing.Extensions.VSTestBridge", "pname": "Microsoft.Testing.Extensions.VSTestBridge",
"version": "1.5.3", "version": "1.9.0",
"hash": "sha256-XpM/yFjhLSsuzyDV+xKubs4V1zVVYiV05E0+N4S1h0g=" "hash": "sha256-CadXLWD093sUDaWhnppzD9LvpxSRqqt93ZEOFiIAPyw="
}, },
{ {
"pname": "Microsoft.Testing.Platform", "pname": "Microsoft.Testing.Platform",
"version": "1.5.3", "version": "1.9.0",
"hash": "sha256-y61Iih6w5D79dmrj2V675mcaeIiHoj1HSa1FRit2BLM=" "hash": "sha256-6nzjoYbJOh7v/GB7d+TDuM0l/xglCshFX6KWjg7+cFI="
}, },
{ {
"pname": "Microsoft.Testing.Platform.MSBuild", "pname": "Microsoft.Testing.Platform.MSBuild",
"version": "1.5.3", "version": "1.9.0",
"hash": "sha256-YspvjE5Jfi587TAfsvfDVJXNrFOkx1B3y1CKV6m7YLY=" "hash": "sha256-/bileP4b+9RZp8yjgS6eynXwc2mohyyzf6p/0LZJd8I="
},
{
"pname": "Microsoft.TestPlatform.AdapterUtilities",
"version": "17.13.0",
"hash": "sha256-Vr+3Tad/h/nk7f/5HMExn3HvCGFCarehFAzJSfCBaOc="
}, },
{ {
"pname": "Microsoft.TestPlatform.ObjectModel", "pname": "Microsoft.TestPlatform.ObjectModel",
"version": "17.12.0", "version": "17.13.0",
"hash": "sha256-3XBHBSuCxggAIlHXmKNQNlPqMqwFlM952Av6RrLw1/w=" "hash": "sha256-6S0fjfj8vA+h6dJVNwLi6oZhYDO/I/6hBZaq2VTW+Uk="
}, },
{ {
"pname": "Microsoft.TestPlatform.ObjectModel", "pname": "Microsoft.TestPlatform.ObjectModel",
"version": "17.14.1", "version": "18.0.0",
"hash": "sha256-QMf6O+w0IT+16Mrzo7wn+N20f3L1/mDhs/qjmEo1rYs=" "hash": "sha256-O/ivHdoIO+q1n0byJ9OZO4quOqACOD3K3Qm00wfhuZk="
}, },
{ {
"pname": "Microsoft.TestPlatform.TestHost", "pname": "Microsoft.TestPlatform.TestHost",
"version": "17.14.1", "version": "18.0.0",
"hash": "sha256-1cxHWcvHRD7orQ3EEEPPxVGEkTpxom1/zoICC9SInJs=" "hash": "sha256-qAIX2Rqxrnh1xaYRjCbkkvvMm407oyKihqyVjURX5wY="
}, },
{ {
"pname": "Myriad.Core", "pname": "Myriad.Core",
@@ -216,8 +221,8 @@
}, },
{ {
"pname": "Nerdbank.GitVersioning", "pname": "Nerdbank.GitVersioning",
"version": "3.8.38-alpha", "version": "3.8.118",
"hash": "sha256-gPMrVbjOZxXoofczF/pn6eVkLhjVSJIyQrLO2oljrDc=" "hash": "sha256-Hmyy0ZKOmwN4zIhI4+MqoN8geZNc1sd033aZJ6APrO8="
}, },
{ {
"pname": "NETStandard.Library", "pname": "NETStandard.Library",
@@ -271,8 +276,8 @@
}, },
{ {
"pname": "NUnit3TestAdapter", "pname": "NUnit3TestAdapter",
"version": "5.0.0", "version": "5.2.0",
"hash": "sha256-7jZM4qAbIzne3AcdFfMbvbgogqpxvVe6q2S7Ls8xQy0=" "hash": "sha256-ybTutL4VkX/fq61mS+O3Ruh+adic4fpv+MKgQ0IZvGg="
}, },
{ {
"pname": "RestEase", "pname": "RestEase",
@@ -376,17 +381,17 @@
}, },
{ {
"pname": "TypeEquality", "pname": "TypeEquality",
"version": "0.3.0", "version": "0.4.2",
"hash": "sha256-V50xAOzzyUJrY+MYPRxtnqW5MVeATXCes89wPprv1r4=" "hash": "sha256-YxK6BGHjcuP76j5BbTDi814jxGqOevQSgS00IJcjZSA="
}, },
{ {
"pname": "WoofWare.Expect", "pname": "WoofWare.Expect",
"version": "0.8.2", "version": "0.8.3",
"hash": "sha256-iqt4FPkUr24/4dnRfh7P5nPNNlaPzaItP6/yrGRrQyo=" "hash": "sha256-Fc4xpqXjD2hMnaR9kxYiXi/Kxhy6T1QA5Xe2XjTM/t8="
}, },
{ {
"pname": "WoofWare.Whippet.Fantomas", "pname": "WoofWare.Whippet.Fantomas",
"version": "0.6.3", "version": "0.6.4",
"hash": "sha256-FkW/HtVp8/HE2k6d7yFpnJcnP3FNNe9kGlkoIWmNgDw=" "hash": "sha256-ScZ7EEcxLvXyam2ZVqDK58QlK3RcePWghzRvtLLLdZI="
} }
] ]