Your problem description is a typical textbook example of when too much blabla about 'this is good, that's bad' becomes the reason why a developer creates the software the way it's created instead of looking at the problem at hand and create software to fix that problem.
Case in point: your problem description isn't your problem to solve: you have an application to create for your client, that's the problem you should solve. If your choice of tools make your life hard, kick them out and use what works: if mocking doesn't work, why bother? Oh, because someone said your software will suck if you don't mock? Why?
You picked up some DDD things here and there, but you've missed some important parts: Product is an aggregate root. This means that you should obtain products from its own repository. Yes, that mitigates the navigation feature in the model, but that's DDD for you, IF you create the repositories strictly how the second part of Evans' book is dictating. But... should you?
If you can't answer why Product has its own repository, yet you can navigate to products from Order, you shouldn't create repositories for aggregate roots. WHY is that repository there? If it's there, shouldn't it be the ONLY point where Products are obtainable? (so also not through lazy loading!).
This indeed will create a lot of overhead and code you likely won't need (so ironically, YAGNI in full effect).
Ok, enough ranting. DDD is all about thinking. So the domain should drive the design, and by practicing that, you'll get a domain model which is representing reality. That's not to say you should implement a lot of code just because you read somewhere you should. Instead, if you have recognized the domain elements, the aggregate roots etc., you then have to place behavior for these types somewhere, e.g. inside the domain classes. You can place fetch logic in separate classes like order oriented fetch logic in an Order repository, but it won't be a repository in the strict sense (e.g. it doesn't have its own local cache etc. ). That's not that bad, it's all about what you should create for your client.
So, first: think, second: think, and third: think... again. What seems logical for you. Make a list of pros/cons of the options you have and choose the one which seems the most right for you. Document that choice and why you picked that one and not the alternatives. This gives way more value to maintainers than any other source: you document the alternatives and why you didn't pick them, you do research what will work for you, and you chose one.
Software engineering isn't hard, it's just that nowadays it seems fashion to simply do first and think later, without proper reasoning why one would do it that way and not the other way.
Good luck :)