I think the solution is very context dependent. Here’s a few solutions in the order I would try them:
Just use the backend
Assuming you control the backend (is the Elm app served by the backend?) you should be able to create a user in your local dev system and use that without making any changes to the Elm code. This is by far the simplest solution and the one I go for first when developing Elm apps.
Pros:
- Simple
- You’re probably already running a local server if the backend hosts the Elm app
- Don’t need to change Elm code
- Making real (local) HTTP requests so you’re using the full stack
Cons:
- You need to control the backend
- You need to run a local server
Fake the backend
If you’re developing against a third-party service, I like to create a small fake app that I’ll run locally that responds to the same API but returns canned responses. I’ve used this technique a lot when integrating backends with third-party services that don’t have a sandbox.
Pros
- Don’t need to change Elm code
- Making real (local) HTTP requests so you’re using the full stack
Cons
- You need to run a local server
- You need to write a fake service
Conditional in the Elm code
Given the following types:
type alias Stubbable a
= Hardcoded a
| GetFromApi
type alias Config =
{ user : Stubbable User
}
type alias Model =
{ config : Config
, currentUser : User
}
you’d probably build up the the Config
record based on flags passed into the app. Then you could write this task-based approach for switching:
fetchUser : Config -> Int -> Cmd Msg
fetchUser config id =
case config.user of
Hardcoded user ->
Task.attempt UserFetched (fetchHardcodedUser user)
GetFromApi ->
Task.attempt UserFetched (fetchUserFromApi id)
fetchUserFromApi : Int -> Task Http.Error User
fetchuserFromApi id =
Http.get ("http://someservice.com/user/" ++ id) userDecoder
|> Http.toTask
fetchHardcodedUser : User -> Task a User
fetchHardcodedUser user =
Task.succeed user
Pros
- More fine-grained control
- Don’t need to run a local server
Cons
- Need to change the Elm code
- Doesn’t exercise the full stack (HTTP could be unimplemented and it would still “work on my machine”)