I struggle with this because I'm just a beginner in F #, and I'm currently involved in the F # learning process by creating unit tests for C # code in F #, as suggested in F # for fun and for profit.
Problem.
I have the following C # class
public class ObjectMapper<TSource, TTarget>
where TTarget : class, new() {
public readonly TSource Source;
public readonly TTarget Target;
public ObjectMapper(TSource source) {
this.Source = source;
this.Target = new TTarget();
}
public ObjectMapper<TSource, TTarget> Populate<T>(
Expression<Func<TTarget, T>> targetAccessor,
Func<TSource, T> sourceValue) {
var targetPropertyInfo = targetAccessor.ToPropertyInfo();
targetPropertyInfo.SetValue(this.Target, sourceValue(this.Source));
return this;
}
}
and I started by trying to write a simple unit test in F #
module CompanyName.Utils.Test.ObjectMapper
open System
open Xunit
open Swensen.Unquote
open Microsoft.FSharp.Linq.RuntimeHelpers // do I need this?
open CompanyName.Utils // the namespace of the C
type Source(name: string, code: int, date: DateTime) =
member thi.Name = name
member this.Code = code
member this.Date = date
type Target() =
member this.Id: string = System.String.Empty
member this.Name: string = System.String.Empty
member this.Code: int = 0
member this.Date: DateTime = System.DateTime.MinValue
[<Fact>]
let ``ObjectMapper.Populate maps property values from source to target``() =
// arrange
let name = @"name"
let code = 123
let date = new System.DateTime(1980,2,15)
let source = Source(name, code, date)
// let target = Target()
let mapper = ObjectMapper<Source, Target>(source)
// act // this is how I would like it to be!
mapper.Populate(t => t.Name, s => s.Name)
mapper.Populate(t => t.Code, s => s.Code)
mapper.Populate(t => t.Date, s => s.Date)
mapper.Populate(t => t.Id, s => s.Date+s.Code+s.Name)
// assert
test<@ mapper.Target.Name = source.Name @>
Assert.Equal(mapper.Target.Name, source.Name)
test<@ mapper.Target.Code = source.Code @>
Assert.Equal(mapper.Target.Code, source.Code)
test<@ mapper.Target.Date = source.Date @>
Assert.Equal(mapper.Target.Date, source.Date)
test<@ mapper.Target.Id = @"1980-2-15123name" @>
Assert.Equal(mapper.Target.Id, @"1980-2-15123name")
Assert.True(false)
, , , , . , , , . , , , , , - , F # , , .
,
- , , , .
- , lambdas F # # , 5-.
- , ,
, , .
, - , , , , F #, #, . , , . , , .
Unquote MSTest , , .
.
Fyodor Soiki
module CompanyName.FSharp.UtilsFunctions
right-thing-to-do-in-f
let strconc =
fun (data) ->
let sb = new System.Text.StringBuilder()
for o in data do sb.Append(o.ToString()) |> ignore
sb.ToString()
strconc ["one"; "two"] |> printfn "%s"
strconc [1;2;3] |> printfn "%s"
strconc (["one"; "two"; 3 ]: list<obj>) |> printfn "%s"
module LogXtreme.Utils.Test.ObjectMapper
open System
open Xunit
open Swensen.Unquote
open CompanyName.Utils
open CompanyName.FSharp.UtilsFunctions
type Source(name: string, code: int, date: DateTime) =
member thi.Name = name
member this.Code = code
member this.Date = date
type Target() =
member val Id: string = System.String.Empty with get, set
member val Name: string = System.String.Empty with get, set
member val Code: int = 0 with get, set
member val Date: DateTime = System.DateTime.MinValue with get, set
[<Fact>]
let ``ObjectMapper.Populate maps property values from source to target``() =
let name = @"name"
let code = 123
let date = new System.DateTime(1980,2,15)
let source = Source(name, code, date)
let mapper = ObjectMapper<Source, Target>(source)
let expectedId = strconc ([source.Name; source.Code; source.Date]: list<obj>)
mapper.Populate((fun t -> t.Name), fun s -> s.Name) |> ignore
mapper.Populate((fun t -> t.Code), fun s -> s.Code) |> ignore
mapper.Populate((fun t -> t.Date), fun s -> s.Date) |> ignore
mapper.Populate((fun t -> t.Id), fun s -> strconc ([s.Name; s.Code; s.Date]: list<obj>)) |> ignore
test<@ mapper.Target.Name = source.Name @>
test<@ mapper.Target.Code = source.Code @>
test<@ mapper.Target.Date = source.Date @>
test<@ mapper.Target.Id = expectedId @>
.