How to write tests using mocks using f #

I would like to write an F # unit test with mock objects. I am using NUnit. But, unfortunately, I could not find examples.

Here is an example of test code:

type ICustomer = interface abstract Id: int with get abstract Name: string with get abstract CalculateBalanceWithDiscount: decimal -> decimal end type Customer = class val id: int val name: string val balance: decimal new(id, name, balance) = {id = id; name = name; balance = balance} interface ICustomer with member this.Id with get () = this.id member this.Name with get () = this.name member this.CalculateBalanceWithDiscount discount = this.balance - (discount * this.balance) end end 
+4
source share
3 answers

As a note, you can use the implicit constructor syntax to make the class declaration more enjoyable. You can also simplify readonly properties because you can omit with get() :

 // F# infers that the type is an interface type ICustomer = abstract Id : int abstract Name : string abstract CalculateBalanceWithDiscount : decimal -> decimal // Parameters of the implicit constructor are autoamtically // accessible in the body (they are stored as fields) type Customer(id:int, name:string, balance:decimal) = interface ICustomer with member this.Id = id member this.Name = name member this.CalculateBalanceWithDiscount(discount) = balance - (discount * balance) 

As for testing - do you have an example of what you are trying to achieve? I am sure that we can help, for example, when translating code from C #. Or what tests would you like to write using mockery?

In general, the good thing about F # and functional languages ​​is that you can usually easily test code without using any layouts. Functional programs are written in a different style:

In functional programming, a function takes all input as arguments, and the only thing it does is that it calculates and returns some result. This is also true for methods of immutable object types - they do not change any state of any objects

Mocks are usually used for two purposes:

  • To make sure that the checked operation made some call to the method of the reference object, for example. prod.Update(newPrice) to update the state of an object. However, in functional programming, a method should instead return a new state as a result - so you don’t need an object layout. Just check if the new return state is expected.

  • To load the created fake application component, for example, instead of loading data from the database. Again, a purely functional function should accept all nested arguments. This means that you do not need to create an object layout - you simply call the function with some test data as an argument (instead of data loaded from the database).

Thus, this means that in a well-designed functional program, you should be able to write all unit tests simply as checks that confirm that some function returns the expected result for the expected arguments. Of course, this is not entirely true in F #, because you may need to interact with other unclean .NET components (but you can only answer them if you give a more specific example).

+8
source

You do not need to create a class to create mocks:

 /// customer : int -> string -> decimal -> ICustomer let customer id name balance = {new ICustomer with member this.Id = id member this.Name = name member this.CalculateBalanceWithDiscount discount = balance - (discount * balance) } 
+5
source
 type ICustomer = interface abstract Id: int with get abstract Name: string with get abstract CalculateBalanceWithDiscount: decimal -> decimal end type Customer = class val id: int val name: string val balance: decimal new(id, name, balance) = {id = id; name = name; balance = balance} interface ICustomer with member this.Id with get () = this.id member this.Name with get () = this.name member this.CalculateBalanceWithDiscount discount = this.balance - (discount * this.balance) end end 
0
source

Source: https://habr.com/ru/post/1305444/


All Articles