iacoware / mocking-frameworks-or-manual-mocks

MIT License
5 stars 1 forks source link

Inmemory repo best practices #2

Open steeeveb opened 5 years ago

steeeveb commented 5 years ago

After many months I was able to adopt this approach doing an exercise and I have to say that it has been really interesting and effective. I've liked it. Maybe it is also because I did it in python, and since I hate the mocks api in the standard library, simply it was a very attractive alternative (in java it would have been more tedious, because, as we know, it is not a concise language). So I want to thank you again for sharing this example. I have a couple of question:

  1. without using a mock library it is impossible to make the usecase test pass at the beginning. I started writing it and then I ignored it after having understood the interactions needed with the InmemoryRepository. Then I wrote in tdd the InmemoryRepository with its contract test and then I returned back to the usecase test. Is it the right process?

  2. do you have any suggestions while writing inmemory repositories? like copy always your objects before returning them from the internal datastructure(to avoid strange interactions) or something like this?

Thanks again

iacoware commented 5 years ago

Thanks for your comment @steeeveb, it's really appreciated. Regarding your questions:

  1. I do my best to make the test pass. Sometimes I put all the code in the object under test, other times I sketch and implement the minimum amount of code needed for the collaborator to be useful (happens more frequently if you start on the query-side of your public API). After that I extract and refine all the interactions during the refactoring phase. This is one key difference (if my understanding is correct ;-)), I don't design internal collaborators interactions during the RED phase but only the public API. Before I bother to look at contract tests I implement more use cases in order to gather more info (Did I understood the problem correctly? Am I happy with the design? Do I see any potential problem? The principle here is to postpone a decision until the "last responsible moment". Did I answer your question?

  2. Not many aside from what you already said about copying object and collections to avoid any reference-sharing issue (object aliasing)

HTH

steeeveb commented 5 years ago

Hi @iacoware, so basically what you are doing can be defined as a more classical tdd approach. In this example, the point is that you are doing the interface discovery using a mocking library and then you replace the designed mock. So, an idea can be to add also a usecase done completely without mocks to this example. In this way you can show how you discover the interfaces with a refactoring step. For the second point, I am wondering if, in a big project, you end up with sharing a lot of code between all the in memory repository implementations, like, I don't know, the autoincrement for ids(silly example, but it is the first one I can imagine).

iacoware commented 5 years ago

Yeah, I guess I'm more inclined towards a classicist approach (which doesn't preclude an outside-in approach). Actually, it's a good idea to have an example where you can compare the two approaches, thanks for the suggestion.

Regarding your second point, usually, it's not a pressing concern. Furthermore, you can leverage all your usual design skill to avoid any duplication that bothers you ;-)