Code that’s easier to understand, maintain, and extend — that’s the promise of Object-Oriented Programming. But the reality for many iOS developers is that our objects are bloated. They know too much, and do too much. …What if our code has hidden objects, waiting to be found?
Each hidden object could provide a new abstraction, a new tool. They could make the code more manageable. Is there a way to discover these hidden objects? Domain-Driven Design provides a way.
Disclosure: The book links below are affiliate links. If you buy anything, I earn a commission, at no extra cost to you.
Eric Evans’ Domain-Driven Design is a book with many facets. One of my big takeaways is that our code often contains concepts that are hidden. The book’s challenge to me is to recognize implicit concepts, and make them explicit.
I stumbled upon this in the TDD sample app. While applying a principle from the book to the Fetch Characters Marvel Service, I uncovered a useful class.
I’ve written about my experience of going to try! Swift Tokyo 2017. Now thanks to the video and transcript provided by Realm, I can also share the talk I gave: “Making Mock Objects More Useful”.
I start by showing the basics of how to make a Swift mock object by hand. But this easily leads to fragile tests because the assertions are overspecified. We need ways to make tests more malleable, with mocks that are more flexible.
Subscribe to Download these FREE Code Snippets
Languages: Swift and Objective-C
IDEs: Xcode and AppCode
You’ll get our newsletter on Clean Code techniques for iOS developers. And you’ll get instant access to these code snippets!
How can we unit test JSON parsing, handling every possible error? Can we generate immutable models? And for Swift, how can we keep our Response Models free of optionals?
Of course, there are many JSON parsing libraries out there. Plug one in, define all fields as non-optional, and you’re good to go! …Until your app crashes, because something was different in the actual JSON data.
Unlikely? “The backend team would never do that to us”? I’ve had a released app crash because the backend folks changed one field from a string to an integer. I’ve seen app development and QA forced to pause because a commit assumed all fields were non-optional. (It crashed on the missing field, because Swift.)
So let’s look at a pattern that will help us
Even if you never plan to do your own parsing, we’ll learn things along the way about design and testing.
If you’re interested in Swift development, and want to visit Japan, start making plans to go to the next try! Swift conference in Tokyo. It was my privilege to be a speaker earlier this month.
Let me share my impressions of the conference, and why you might consider making the trip there.
(But first, a side-note about this blog: Sorry I’ve been so quiet lately! I was spending my time preparing for try! Swift Tokyo 2017. Next up is CocoaConf Chicago, where I’ll be leading a TDD workshop in addition to giving a talk. But I’ve also continued to TDD a JSON parsing example, in both Objective-C and Swift versions, so I have plenty to blog about. To make sure you don’t miss any new articles, you can sign up to get updates via email.)
Enumerations with associated values are my favorite feature of Swift. But how can we write unit tests against them? “Make them Equatable and use XCTAssertEqual” is common advice.
I’m here to argue otherwise. In fact, let’s use this as a jumping-off point to discuss Swift Equatables in unit tests.
Uncle Bob set off another firestorm with his blog post The Dark Path. Condemnation from the Swift programming community was, well, swift. How dare he insult our wonderful new language? Clearly he’s a n00b who hasn’t done enough Swift programming.
Except that he’s no n00b — not even close. As Mark Seemann said,
Perhaps you disagree with @unclebobmartin (at times I do), but remember: he's been programming all of YOUR LIFE. Don't presume him ignorant.
— Mark Seemann (@ploeh) January 14, 2017
I’m here to defend Uncle Bob’s post, as it relates to unit testing and TDD.
How can we use Test-Driven Development for JSON parsing? Most developers are concerned with ways to implement the production code. There are various approaches, various libraries… But what about the unit test side of things?
If we write effective unit tests, the design can appear incrementally. And with a strong suite of tests, you’re free to change the implementation — even radically. When the results are guaranteed by tests, whatever approach you take or library you use becomes an implementation detail!
Last time, we looked at design principles, such as sticking to the Single Responsibility Principle and returning a Response Model. This time, let’s look at:
When you’re new to Test-Driven Development, there’s a strong tendency to continue writing code the way you used to. Then you step back and ask, “But how can you unit test this? TDD is so impractical!”
Almost always, my answer is: “Then don’t write it like that.”
Apple published a blog post, Working with JSON in Swift. I was looking for tips on Swift JSON parsing, and found the beginning of the article quite helpful. But it took a bad turn at the end…
I’ve shown you how to replace real objects with fakes in Swift, so that you can begin creating useful Swift mock objects. We did this by moving away from a concrete type to a protocol. Anything that implements the protocol will work, so fakes are no problem.
But what do we do when we can’t change the signature? How do we substitute fake arguments, or a fake return value?
It’s time to talk about partial mocks in Swift.
Last time, we looked at How Does Swift Support Stubbing and Mocking? Swift’s
extension declaration opens the way, letting us attach new protocols to existing classes. That much is well-known in the Swift community.
But then what? How do we create useful Swift mock objects? I’ve seen many examples that are okay… to start with. But in the long run, I’m afraid they’ll fall short for ongoing maintenance.
I wrote OCMockito because I wanted Objective-C mock objects that struck a better balance between “precise” and “forgiving”. I also wanted test code that was easier to read and write. What can we do with Swift mocking?