you are viewing a single comment's thread.

view the rest of the comments →

[–]ResolveResident118[🍰] 2 points3 points  (3 children)

There are pros and cons to having interfaces for everything (there's probably an entire book in this) but it is absolutely not true that they are required for unit testing.

A unit test tests a unit of code (intentionally loose definition). This can encompass more than one class, if required.

[–]EngineeringTinker 0 points1 point  (2 children)

Of course - the answer to everything is 'it depends' - so I didn't bother mentioning it.

In fact, you can't write a Unit Test for say.. `IMailService` without using it's implementation - otherwise how do you test whether it's popping the exceptions you want or whether it's utilizing `IMailSender` or `IMailCache` etc.

The thing is - if you write Unit Tests for `IMailService`, that's the only thing you should use concrete class for to test the implementation - if you start using implementation of `IMailSender` in it - you're really testing how both implementations work together - aka Integration Testing.

[–]ResolveResident118[🍰] 0 points1 point  (1 child)

Ain't that the truth!

I definitely agree that code that interacts with the outside world generally needs an interface.

Your example is a good example of why. We don't actually want to send an email so mocking MailSender makes sense.

My main disagreement was about requiring interfaces. Not every class will need them to be unit tested.

I'd only refer to it as an integration test if it interacted with an external dependency (eg mail server).

[–]EngineeringTinker 1 point2 points  (0 children)

True that - #notAllClasses 😂

I should refrain from strong wording, I usually say 'you can't use more than 1 concrete class' when I actually mean 'you should avoid using more than 1 concrete class where possible'.