Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock dependency in Elm

In every elm file, dependencies to be imported are declared at the top. Is there a way, while testing the application, to mock a dependency?

For example, suppose I have an application using the HTTP module to make an ajax request. When I test my module, I would like to avoid to make the actual ajax request, but I'd like to have a mocked HTTP module which will return a fake response just for the sake of testing.

How could I do this?

like image 975
marcosh Avatar asked Feb 01 '16 15:02

marcosh


2 Answers

Since Elm is a pure functional language, you often don't need to do any kind of mocking because side effects are limited to interaction with ports. Most of the time, you can just call the function you want to test directly.

Consider this typical example of an HTTP request task being mapped to an Action:

type alias MyThing =
  { id : Int
  , name : String
  }

type Action
  = FetchData
  | ErrorOccurred String
  | DataFetched MyThing

myDecoder : Json.Decoder MyThing
myDecoder =
  Json.object2
    MyThing
    ("id" := Json.int) 
    ("name" := Json.string) 

fetchData : Effects Action
fetchData =
  Http.get myDecoder url
    |> Task.toResult
    |> Task.map httpResultToAction
    |> Effects.task

httpResultToAction : Result Http.Error MyThing -> Action
httpResultToAction result =
  case result of
    Ok thing ->
      DataFetched thing
    Err err ->
      ErrorOccurred (toString err)

There are a few things that would benefit from testing here, but none of them require mocking.

You may want to test the JSON decoding of myDecoder. You could simply create some good and bad JSON strings and use Json.Decode.decodeString with myDecoder to test that the end result meets your expectation.

The thing that is probably most in need of unit testing is the httpResultToAction function. Again, in this example, this requires no mocking. All you need to do is create a number of good and bad Result values and test your expectations.

like image 70
Chad Gilbert Avatar answered Nov 13 '22 00:11

Chad Gilbert


You should separate the code that calls into the Http module from the real logic you want to test.

For example, if you write a function that takes a Result Error String as an argument (such as might come back from a call to Http.getString) you can easily unit test that function without needing to make a real HTTP call.

like image 34
Andy Balaam Avatar answered Nov 13 '22 01:11

Andy Balaam