Permalink
Browse files

Added naive, DI-like implementation

  • Loading branch information...
ploeh committed Dec 10, 2016
1 parent 7bdf3e3 commit d2387cceb81eabc349a63ab7df1249236e9b1d13
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<Paket>True</Paket>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535" newVersion="4.4.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -33,18 +33,6 @@
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Release\BookingApi.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
</ItemGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
@@ -251,4 +239,20 @@
</ItemGroup>
</When>
</Choose>
<ItemGroup>
<Content Include="App.config" />
<Compile Include="AssemblyInfo.fs" />
<Compile Include="MaîtreD.fs" />
<Compile Include="Composition.fs" />
<Compile Include="MaîtreDTests.fs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
</Project>
@@ -0,0 +1,17 @@
module Ploeh.Samples.Composition
// Dirty, lying module that pretends to implement real SQL operations
module DB =
let readReservations connectionString date = []
let createReservation connectionString reservation = 0
open MaîtreD
// More pretension
let connectionString = ""
// Reservation -> int option
let tryAcceptComposition reservation =
let read = DB.readReservations connectionString
let create = DB.createReservation connectionString
tryAccept 10 read create reservation
@@ -0,0 +1,18 @@
module Ploeh.Samples.MaîtreD
open System
type Reservation = {
Date : DateTimeOffset
Quantity : int
IsAccepted : bool
}
// int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation
// -> int option
let tryAccept capacity readReservations createReservation reservation =
let reservedSeats =
readReservations reservation.Date |> List.sumBy (fun x -> x.Quantity)
if reservedSeats + reservation.Quantity <= capacity
then createReservation { reservation with IsAccepted = true } |> Some
else None
@@ -0,0 +1,58 @@
module Ploeh.Samples.MaîtreDTests
open Ploeh.Samples.MaîtreD
open FsCheck
open FsCheck.Xunit
open Swensen.Unquote
// 'Guard' composition. Returns the return value if ``assert`` doesn't throw.
let (>>!) ``assert`` returnValue x =
``assert`` x
returnValue
module Tuple2 =
let curry f x y = f (x, y)
module Gen =
let reservation = gen {
let! PositiveInt quantity = Arb.generate
let! reservation = Arb.generate
return { reservation with Quantity = quantity } }
[<Property(QuietOnSuccess = true)>]
let ``tryAccept behaves correctly when it can accept``
(NonNegativeInt excessCapacity)
(expected : int) =
Tuple2.curry id
<!> Gen.reservation
<*> Gen.listOf Gen.reservation
|> Arb.fromGen |> Prop.forAll <| fun (reservation, reservations) ->
let capacity =
excessCapacity
+ (reservations |> List.sumBy (fun x -> x.Quantity))
+ reservation.Quantity
let readReservations = ((=!) reservation.Date) >>! reservations
let createReservation =
((=!) { reservation with IsAccepted = true }) >>! expected
let actual =
tryAccept capacity readReservations createReservation reservation
Some expected =! actual
[<Property(QuietOnSuccess = true)>]
let ``tryAccept behaves correctly when it can't accept``
(PositiveInt lackingCapacity) =
Tuple2.curry id
<!> Gen.reservation
<*> Gen.listOf Gen.reservation
|> Arb.fromGen |> Prop.forAll <| fun (reservation, reservations) ->
let capacity =
(reservations |> List.sumBy (fun x -> x.Quantity)) - lackingCapacity
let readReservations _ = reservations
let createReservation _ = failwith "Mock shouldn't be called."
let actual =
tryAccept capacity readReservations createReservation reservation
None =! actual
View
@@ -1,12 +1,18 @@
#r @"packages/FAKE/tools/FakeLib.dll"
open Fake
open Fake.Testing
Target "Build" <| fun _ ->
!! "**/BookingApi.sln"
|> MSBuildRelease "" "Rebuild"
|> ignore
Target "Test" <| fun _ ->
!! "*/bin/Release/Ploeh.Samples.*.dll"
|> xUnit2 (fun p -> { p with Parallel = ParallelMode.All })
"Build"
==> "Test"
RunTargetOrDefault "Build"
RunTargetOrDefault "Test"

0 comments on commit d2387cc

Please sign in to comment.