"Should I write Unit Test for a Repository class?"

Поділитися
Вставка
  • Опубліковано 25 жов 2024

КОМЕНТАРІ • 34

  • @RonaldCabreraGonzalez
    @RonaldCabreraGonzalez 2 місяці тому +20

    Please do the video about specification pattern, also your view about unit tests was pretty constructive.

    • @Rick104547
      @Rick104547 2 місяці тому +1

      Yeah would love to see it. Working with an architect currently who insists on using that pattern but we end up going through all kinds of hoops to get back the support for certain operations that you already have normally. We have to use ardalis for it though and are not allowed to use an alternative way. I would much prefer using extension methods and you could even go the delegate way if you really need to inject specifications somewhere.

    • @gui.ferreira
      @gui.ferreira  2 місяці тому +1

      Added to the pipeline 😉

  • @MarkRendle
    @MarkRendle 2 місяці тому

    Yay! See you in Porto!

  • @xaberue
    @xaberue 2 місяці тому +1

    Hi Gui!
    Great video explaining the historial why of the repositories, the sense of having them and/or testing them, and showing an alternative...
    And yes please, do a video explaining the Specification pattern!
    Thanks again

  • @Fikusiklol
    @Fikusiklol 2 місяці тому

    Hello.
    How come not having a repo here doesnt break encapsulation?
    How come having "too many" get methods breaks SRP? We are just working with database and then entire DbContext is a big SRP breaker. Interfaces also a thing.
    There are things called Read/Write models and CQRS for a reason.
    Repos for writes belong to domain layer, cause those "too many" get methods should come from a business.
    TLDR:
    you unit test repo if it has any mapping logic, you can integration test it independently if you want.

  • @piotrkowalski3460
    @piotrkowalski3460 2 місяці тому +4

    Please don't unit test repositories.
    Write integration tests for your use cases with a real database. It will cover your data access testing, whether you use repositories or not. Be pragmatic.

    • @gui.ferreira
      @gui.ferreira  2 місяці тому

      As I said in the video. A Repository is a Mapper to an external dependency.

  • @WhisperII
    @WhisperII 2 місяці тому +1

    Great viseo. Would be nice to have a video about specification pattern, thanks!

  • @Timelog88
    @Timelog88 2 місяці тому

    The two question that remain in my head:
    1. When using domain centric architecture, shouldn't you use interfaces declared in your domain to be implemented by infrastructure logic? How does that work with efcore DBContext?
    2. Microsoft explicitly says to not use the in memory provider due to compatibility limitations, what's your reason for promoting it and would you agree using sqlite in memory would still be a unit test?

    • @juniorzucareli
      @juniorzucareli 2 місяці тому

      This argument of creating abstraction in the core and implementing it outside of it comes from clean architecture, hexagonal architecture, etc.
      Usually the argument for this is for the application to be "service agnostic", but in the real world, this is often utopian.
      - Your application will not change its database.
      - Your application will not change its framework.
      - Your application will respond to only its webapi, not to N types of services (queue, mobile), etc.
      If you have requirements that require you to create abstractions, create the abstraction, but there will be a requirement for this, and do not abstract everything just to follow an architecture.
      The example in the video is with EF, and it is a very realistic example. Many devs create this abstraction with the repository, which makes no sense at all. EF is already a repository.

    • @Timelog88
      @Timelog88 2 місяці тому +1

      @@juniorzucareli I literary am working on a project were it already happened 4! times in the past 2 years in different parts of the codebase. And currently there are talk to also replace elasticsearch so that would be a fifth time. All due to reasons outside our control.....
      So, often utopian, sure, but I would've been very glad if we would've done it from the start as that would have saved us many headaches.

    • @gui.ferreira
      @gui.ferreira  2 місяці тому

      1. The case presented on the Reddit question isn't a case of a domain centric architecture. As the author of the question mentions, he is calling the Repo from the Controller. Domain Centric Architectures change the answer slightly. In a case like that, I want to push the code that interacts with external dependencies to the edges.
      2. Can you point me to where Microsoft says that? I confess I never heard about such a recommendation. As far as I know, it's explicit that it's not recommended for production, but only for testing.

    • @Timelog88
      @Timelog88 2 місяці тому +1

      @@gui.ferreira Thanks for the comment.
      For the in memory database, Microsoft mentions that in the documentation about testinf efcore applications:
      "The in-memory provider will not behave like your real database in many important ways. Some features cannot be tested with it at all (e.g. transactions, raw SQL..), while other features may behave differently than your production database (e.g. case-sensitivity in queries). While in-memory can work for simple, constrained query scenarios, it is highly limited and we discourage its use."
      As well as in the documentation for the in-memory provider itself.
      (edit: I tried to add a link but then the comment seems to be auto removed. It you have enabled the option to hold for moderation, then sorry for the spam 🙈)

  • @galberts
    @galberts Місяць тому

    Always the argument that you don't want to depend on the db, and should be able to swap to a different kind of db. Only I have never seen this actually happening, so i think this argument is rarely valid

    • @gui.ferreira
      @gui.ferreira  Місяць тому

      I’ve seen it happening in high-growth companies. And technically, I swap it for most of my tests.

  • @padnom4991
    @padnom4991 2 місяці тому

    Thx again for your video.
    I have difficulty understanding.
    Because if I have a GenreService class with a lot of business logic that calls this repository.
    If I remove GenreRepository, I will then have to inject the DbContext directly into my service class.
    As a result, regarding unit tests, I will no longer be able to use a fake repository?
    Furthermore, can we have repositories in some cases and not in others? How does that affect the coherence of the project?

    • @juniorzucareli
      @juniorzucareli 2 місяці тому

      I think you have to go back a bit and ask yourself, why should I do a unit test on a service class that accesses the database? That doesn't make sense to me. Mocking the database, for me, is a weak test and doesn't have much value. Integration tests should be used for logic that involves the DB in some way.
      Unit tests work well on domain classes, which have state and behavior, and you don't need a service class for that.
      Service classes in general are an unnecessary abstraction. Of course, if this service class is called in several places, that's ok. If not, it's an unnecessary abstraction just to follow "by the book."
      But, if you really want to do a unit test on a service class, just use ef inmemory and your problem will be solved.

    • @padnom4991
      @padnom4991 2 місяці тому

      @@juniorzucareli
      I don't understand.
      In lot of project I saw.
      Generally you have controllers then services ,then the repositories
      You can have lot of logical in services.
      Not all projects are with clean ,onion, architecture.
      So you don't have necessary a domain or application layer.
      For me a service often can acces to the database but the database should be a detail.

    • @gui.ferreira
      @gui.ferreira  2 місяці тому

      As I said in the video, EF with an InMemoryProvider is in fact a Fake.

  • @TerkelBrix
    @TerkelBrix 2 місяці тому +1

    Yes please to specification pattern 🎉👍👌

  • @z0n_
    @z0n_ 2 місяці тому

    Before people start spamming that these EF-wrapper-repositories are useless. There is real use case for these repositories when you want to restrict access to only specific entities (aggregate roots most likely). EF just gives you way too much freedom when using it for mutations. It's so easy to accidentally skip domain logic when you can just query any entity from any point of tree or fetch the root only partially.
    I usually use EF only for mutations and query with something else, like Dapper for example (cqrs style).

    • @Timelog88
      @Timelog88 2 місяці тому

      You don't have to publicly map all entities with efcore though. You can add only the aggregate root to the context and map the rest using the onmodelcreating method. Add that to the fact you can use a separate context for each domain and you really don't need the repository pattern to restrict access.

    • @z0n_
      @z0n_ 2 місяці тому

      @@Timelog88 You can still query every entity in context with `DbContext.Entry()` or with `DbContext.Find()` and you get access to `DbContext.Add` and `DbContext.AddRange`. So you are not really restricting anything unless you are willing to make every non-aggregate-root entity `internal`.
      "you can use a separate context for each domain" - I am talking inside a single bounded context.

    • @z0n_
      @z0n_ 2 місяці тому

      You can still query every entity in context with `DbContext.Entry()` or with `DbContext.Find()` and you get access to `DbContext.Add` and `DbContext.AddRange`. So you are not really restricting anything unless you are willing to make every non-aggregate-root entity `internal`.
      "you can use a separate context for each domain" - I am talking inside a single bounded context.

    • @Timelog88
      @Timelog88 2 місяці тому

      @@z0n_ Quite sure you can't with good encapsulation. Will check if I can get an example up and running tomorrow.

  • @yaghiyahbrenner8902
    @yaghiyahbrenner8902 2 місяці тому +6

    This nonsense started with Java and followed by DDD books for enterprise corp coders, its dead. use a Dao NH Session(), EF Context() are by nature a Repository, the years of people writing classes on top of classes..

    • @krccmsitp2884
      @krccmsitp2884 2 місяці тому +1

      The repository in DDD is different to "other" repositories.

    • @yaghiyahbrenner8902
      @yaghiyahbrenner8902 2 місяці тому

      Hate it all. abstractions with no benefits. If you work with large data sets, you end up with direct calls to the db with optimizations.

    • @relicsoft
      @relicsoft 2 місяці тому

      Make sense.