There’s a rule that says
Only mock objects that you own.
I think I understand the reason for this – mocking classes supplied by the frameworks might result in strange behaviour.
What’s the alternative?
What about when you need a dummy date using NSDate?
In the past I’ve swizzled the date method from NSDate to my own class – NSDateMock – but something tells me that’s really wrong!
One Solution – A Wrapper?
Create a wrapper round NSDate, but then you’d have to implement all it’s methods.
Or would you just implement the ones you were using? It seems a messy way of doing it.
My Question
What’s a good way of mocking classes you don’t own such as NSDate?
Update 1
I found this article on mocking which seems to imply that writing a thin wrapper is the way to go. I’m not quite sure why but I feel like this is a hack. Then again, it could make the code more expressive.
But that raises the question, in the case of NSDate do you inject the wrapper class into every single class that needs to know the date?! Surely not…
Update 2
There have been some good answers on this question, but I’m still holding out for other answers – there must be a definitive way of doing this, surely? I still don’t see how categories are going to give me a dummy object I can control either.
In general this is a “how to mock a static/class level method” question, which googling shows a lot of different ideas, so it mainly comes down to taste.
I consider partial mocks to be a code smell as it shows that your class under test (CUT) isn’t testable -> time to refactor.
I’ve tackled this in 2 ways in the past:
1.) Pass a DateProvider (which is an interface) into the constructor of the CUT
At test time this is your MockDateProvider which you can change the state from your test class. I might use a public static field that I can change in my tests
In the real system it just has the date creation method you used.
I might make 2 constructors, one that takes this interface and another which uses the RealDateProvider without any production classes needing to pass in the object.
This is the preferable OO way of doing things. I think!
2.) Make your own static date provider that you can override the behaviour of.
Rather than LibraryDateMaker.newDate() you make a ConfigurableDateMaker.newDate() static. This uses the same objects as 1, but has a setter to allow you to change the behaviour to the mock provider as required. Defaulting to real.
The advantage of this is you don’t have to pass anything into your constructors and you get to keep using a static method for a very common activity.
In brief, the CUT calls ConfigurableDateMaker.newDate(). Which by default returns a real date, but in your test class you can set the behaviour to use the mock before calling the CUT.
Hopefully that makes some sense.