I'd like to write F# unit test with mock objects. I'm using NUnit. But unfortunately I couldn't find any examples.
Here's an example of the code under test:
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
As a side-note, you can use implicit constructor syntax to make your class declaration a bit nicer. 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)
Regarding testing - do you have any example of what you're trying to achieve? I'm sure we can help for example with translating code from C#. Or what kind of tests would you like to write using mocking?
In general, a nice thing about F# and functional languages is that you can usually test code more easily without using any mocks. Functional programs are written in a different style:
In functional programming, a function takes all it's inputs as arguments and the only thing that it does is that it calculates and returns some result. This is also true for methods of immutable object types - they do not modify any state of any objects
Mocks are typically used for two purposes:
To verify that the tested operation performed some call to a method of a referenced object e.g. prod.Update(newPrice)
to update the state of the object. However, in functional programming the method should instead return the new state as the result - so you don't need mock object. Just check whether the new returned state is what you expected.
To load create a fake component of the application, for example instead of loading data from the database. Again, a purely functional function should take all it's inputs as arguments. This means that you don't need to create a mock object - you just call the function with some test data as argument (instead of data loaded from database).
In summary, this means that in a well-designed functional program, you should be able to write all unit tests simply as checks that verify that some function returns the expected result for the expected arguments. Of course, this isn't strictly true in F#, because you may need to interoperate with other impure .NET components (but that can be answered only if you give a more specific example).
You don't need to create a class in order 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) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With