The typical way to test a repository is to create an in memory database and manually load data into it.
This sucks.
If you directly use the dbcontext in your service layer, then you have to populate data for every edge case to test it.
Make a super simple repository with no logic, and you only need 1 test case per method. Then in your service layer you mock the repository and tell it to return any random object you need.
How I think about repositories:
These are simple wrappers around database calls that have few or no dependencies. If I'm adding dependencies here, then they'll either be a cache or a logger.
Make repositories as simple as possible, because texting them sucks. You make a repository because it makes unit testing your service easier.
How I think about services:
Services are just groups of related methods. In a simple CRUD API, I would typically do a service per controller and include all business logic at the service level.
How I think about controllers:
These should be treated like repositories and only contain logic for determining which response code to send.
The general idea is to not test things that need to be mocked, keep all logic out of those and keep them at the edges of the application. Then you test the remaining 90% of your code which would ideally be pure functions that don't need mocks .
The remaining 5% can be integration tests which doesn't care about DI.
In reality this doesn't always work, because sometimes it's better to write a complex query with logic and let your database do the processing.
This is the closest job that I could think of to an open source advocate.
What's your background? I've mainly used language with huge standard libraries and Go's intentionally small standard library feels very unergonomic sometimes (I miss sets).
Elixir feels very ergonomic to me, but a lot of programmers struggle with the lack of typing.