Kolos65 / Mockable

A Swift macro driven auto-mocking library.
MIT License
233 stars 18 forks source link

How to enable protocol Mockability for testing only without introducing a dependency between the main application and your library #41

Closed david-spaeth closed 5 months ago

david-spaeth commented 5 months ago

Hi,

I think my problem has no solution. I would like to make my protocols not dependent on your library and be able to use the @Mockable macro only in a test target on my protocols. My first approach was to try using an extension like this:

@Mockable
extension MessagesManipulator {

}

Obviously, this doesn't work. My second approach was to try using inheritance, but as your documentation indicates, that doesn't work.

I would like to know if you have any suggestions for me to explore before I consider other approaches?

Thank you.

Kolos65 commented 5 months ago

Hi @david-spaeth!

Attached macros only have access to syntax of what they are attached to. For this reason (as you have already answered) you cannot use the macro with extensions or any other location than the original protocol definition.

If you would like to use my package, you need to add it as a dependency to your main target where you define your protocols.

You can however exclude the generated mock implementations from release builds using compile conditions by following the configuration guide.

Can you elaborate on why you would prefer not adding the package?

Let me know if you have any other questions regarding Mockable!

david-spaeth commented 5 months ago

Hi,

Thank you for this feedback; it's exactly what I was expecting, and this limitation on macros is really unfortunate.

I'm working on a side project to create a Swift backend using Vapor. I've been coding quite a bit of complex backend stuff lately in various languages and have been frustrated not being able to solve some problems as I would in Swift. I have the feeling that Swift is underrated and should be more in the spotlight. I'm putting my beliefs to the test with this side project.

In previous backends I've developed, I've applied strong code isolation, following practices like hexagonal and clean architecture. In the current case, this kind of architecture might be a bit overkill for what I need to do, but I have something to prove to myself.

That's why I don't want to tie my business/core layer to your package because it would make it dependent and break the architecture I'm trying to implement. However, I'm completely open to making concessions if justified. Your package seems to be the most advanced among all mock solutions based on annotations; I haven't ruled out using it yet.

Thanks again for your response and your work.

Kolos65 commented 5 months ago

I get your points, I also like to think twice before adding a dependency to my project.

Im not exactly sure how using the package breaks you architecture as it would only affect the way you write unit tests. And for that, it will spare you creating manual mocks or running code generation scripts that use Sourcery or similar.

Of course I'm biased, but I would give it a try if I were you! 😃

Happy coding!

david-spaeth commented 5 months ago

Im not exactly sure how using the package breaks you architecture as it would only affect the way you write unit tests.

The idea here is that the business layer should only depend on itself and not concern itself with technical matters.

It should be a standalone package with zero dependencies. It's an idealistic notion; strictly adhering to this principle can be counterproductive. In reality, we accept that certain external dependencies are integral to our business layer ( for tests for example).

Let's be honest, this kind of architecture is only truly useful in very rare cases, typically with sensitive applications, but the vision it embodies is interesting.

Looking forward to further discussions with you!

Kolos65 commented 5 months ago

I see, we also adopt clean architecture where the domain layer should have no dependencies.

Strictly speaking this would break that requirement, but if you think about it, its not really a true dependency as you can always remove it at any time without breaking any of your business logic.

david-spaeth commented 5 months ago

This response is so spot-on. Thank you for giving me a new angle to think about.