Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing Decorator Pattern #25

Open
mohammadtaherri opened this issue Mar 20, 2024 · 3 comments
Open

Testing Decorator Pattern #25

mohammadtaherri opened this issue Mar 20, 2024 · 3 comments

Comments

@mohammadtaherri
Copy link

mohammadtaherri commented Mar 20, 2024

Hi

How should we test decorators?
For example for testing the DatabaseRetryDecorator, we should mock ICommandHandler to throws an exception. Right?
But based on your unit testing book and fragile tests, We can use mocks just for unmanaged dependencies.
how to test Decorator pattern?

@vkhorikov
Copy link
Owner

Great question. This area is something where the recommendations from my book are lacking a bit. Ideally, you want to re-create the state under test in managed dependency itself (e.g the database), but for some test cases, it's difficult to do. For example, you can't easily put the DB into a state where it would reject requests so that you can test the retry logic. So instead, you have to mock it.

This is the only exception to the rule I described in the book -- i.e when the managed dependency is hard/impossible to bring to the desired state.

Note that you shouldn't mock ICommandHandler, but the database itself, to make sure the whole chain of middleware is working properly.

@mohammadtaherri
Copy link
Author

mohammadtaherri commented Jul 4, 2024

Note that you shouldn't mock ICommandHandler, but the database itself, to make sure the whole chain of middleware is working properly.

Thanks Vladimir.
But DatabaseRetryDecorator uses an ICommandHandler. how do i mock database?
You mean I should test the DatabaseRetryDecorator with another commands?

for example should i create DatabaseRetryDecorator(DisenrollCommand(...)) and then pass the mocked database to DisenrollCommand?

But if I want to do this, then I have to write test for all commands, whenever I add a new decorator!!! And if I want to test decorators separately, then how do I pass them a mocked version of database?

another solution that occurs to me is to create a CustomCommand for tests and pass a database to it and then use it to test DatabaseRetryDecorator.

What do you mean by mocking database to test DatabaseRetryDecorator? And in general, what is the best way to test decorators?

@vkhorikov
Copy link
Owner

vkhorikov commented Aug 11, 2024

for example should i create DatabaseRetryDecorator(DisenrollCommand(...)) and then pass the mocked database to DisenrollCommand?

That's correct. You don't need to test all commands that are using that decorator, though, just one is enough.

An alternative here would be to just test the decorator manually. I know it doesn't sound right but sometimes writing a test just isn't worth it. An example could be an external dependency or a cross-cutting concern like this decorator. You can test it manually once, to make sure it works and then re-test it every time you make changes to it. You can also observe its behavior through logs whenever a database failure happens in dev/qa/prod environments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants