Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a test double in OCaml

How usual is to have a test double in OCaml that would fake a database connection ?

Lets say you want to test a small API on top of a database and the way this works is by providing a Connection type to each function that API exposes.

Something like:

let get_data connection = do_something_with_connection

How would this be unit tested ?

On a larger note is is this kind of testing usual in OCaml, given the fact that OCaml's powerful type system already makes sure that you don't make weird mistakes ?

like image 968
hyperboreean Avatar asked Aug 19 '11 18:08

hyperboreean


Video Answer


2 Answers

You would create an object which has all of the same method names as Connection each with the same signatures (and with stub functionality, obviously). Then you can instantiate one of these objects and declare it as being a Connection via subtyping. Then it can be passed into any of the functions.

Here is a helpful bit about subtyping (which, it should be noted, is not the same things as inheritance in Ocaml).

like image 125
Keith Irwin Avatar answered Oct 11 '22 08:10

Keith Irwin


Build your module with a functor, which takes the Connection module as its argument. Then you can stub out the Connection module in your tests.

So, for example, your db.ml file could look kind of like this:

(* The interface of Connection that we use *)                                                                                                      
module type CONNECTION = sig
  type t
  val execute : string -> t -> string list
end

(* functor to build Db modules, given a Connection module *)
module Make(Connection : CONNECTION) = struct
  ...
  let get_data connection =
    do_something_with (Connection.execute "some query" connection)
  ...
end

Then in your test_db.ml you can just stub out the Connection module

let test_get_data () =
  let module TestConnection = struct
    type t = unit
    let execute _ _ = ["data"]
  end in
  let module TestDb = Db.Make(TestConnection) in

  assert (TestDb.get_data () = ["munged data"])
like image 36
rapha Avatar answered Oct 11 '22 08:10

rapha