This has been discussed in the past but my advice is simply don't.
Ecto already decouples the model from the repository. You can manipulate changesets, perform validations and so on without ever touching the repository. Therefore, you can test all of those things directly and concurrently. On the other hand, there is no way to effectively test things like queries without going through the repository so although you do need the repository in this case, mocking makes no sense.
My advice here is: keep all "pure" code, code that does not depend on the Repo, in the model and have one place where you are going to do all side-effects and database operations. In a Phoenix application, the place for side-effects would be the controller that would invoke many "services" like the repository, sending e-mails and so on. You will write controller tests as integration tests because the job of the controller is *to integrate layers*. Mocking the repo in controller tests make no sense because, every time you mock your own component, you still need an integration test that guarantees everything works, so what is the mock giving you anyway?
To sum up:
* models - is about data transformation. You will build changesets and queries but never reach a service, like the repo or e-mails, from your model
* controllers - is about integrating layers. It gets data from models (like changesets, queries) and send them to services (talking to the database, sending e-mails, etc). Controllers should be kept simple because it should be only about integrating layers
* views - is also about data transformation. In this case, transforming the controller assigns (current user, fetched models) into templates/strings
Which means that, in terms of testing we have (let's use User as an example):
* test/models/user_test.exs - you will test your changeset and others. Again, only data transformation, tests can be "async: true" because it doesn't talk to the database.
* test/models/user_repo_test.exs - you will test anything the model returns that needs the repository to be tested, like complex queries. Here it makes no sense to mock because you *need* the repo, testing a complex query against a fake repo makes no purpose. Also, since it depends on the Repo, tests cannot be concurrent (until Ecto 1.1 where we solve this problem)
* test/views/user_test.exs - you will test how your views are rendered. Again, it is only data transformation, so tests can be "async: true" because it doesn't talk to the database.
* test/controllers/user_controller_test.exs - integration layer. You'll test a simple pass through the different layers and the expected result. Important: you are not going to test "models" and "views" combinations here. For example, you won't test that when you POST attributes A and B, field C will be added to the model. That's is going to be in the model test. In the same way you are not going to test how users with different attributes are rendered. That's in the view test.