To mock or not to mock

I’ve written a book to teach you how to write unit tests effectively. If you want to make your tests fast so you’ll actually run them and run them often to receive immediate feedback, check out Effective Unit Testing. You’ll develop the confidence that your change will not break existing features, and never have to worry about introducing regression. Write non-fragile unit tests that are assets, not liabilities. Use TDD to write testable code that drives feature development.

You can’t talk about unit testing and TDD without mentioning mocks. But what are mocks, really?

In talking to other iOS developers, I frequently see comments such as:

I used to go crazy and write test for every IBOutlet. I would mock every UILabel to verify that they get the correct text based on my models. But it was very time consuming. It was such an overkill. Now I only test if I have complicated logic.

This post serves as a primer to mocking in iOS. It attempts to answer the five Ws and two Hs.

  • Who should mock?
  • Why do you want to mock?
  • When do you want to mock?
  • What do you mock?
  • Where do you put your mocks?
  • How do you mock in a Swift iOS project?
  • How much do you mock?

Continue reading →

Testing View Controller – Part 2

I’ve written a book to teach you how to write unit tests effectively. If you want to make your tests fast so you’ll actually run them and run them often to receive immediate feedback, check out Effective Unit Testing. You’ll develop the confidence that your change will not break existing features, and never have to worry about introducing regression. Write non-fragile unit tests that are assets, not liabilities. Use TDD to write testable code that drives feature development.

Last week in part 1, you wrote tests for the expiration date picker and shipping method picker. You also learned about the role of the invisible UI component in the Clean Swift VIP cycle and how it helps when writing tests for your view controllers.

But the battle against the massive view controller is only half fought.

Today, in part 2, you’ll finish testing the rest of the view controller – text fields and picker configurations. You’ll see some advanced tricks to make your test environment mimic the real app running environment.

Let’s K.O. the massive view controller.

Making text fields play nice with the keyboard

Now that you’ve tested both pickers, what about the text fields? It’ll certainly be nice to know the keyboard behaves as expected when the text fields gain/lose focus.

The text fields are part of the UI component. Interacting with them invokes the UITextFieldDelegate methods. As you’ve already seen with the UIPickerViewDataSource and UIPickerViewDelegate protocols, CreateOrderViewController’s conformance to the UITextFieldDelegate protocol makes it responsible for handling text field events.

Let’s write the tests for these delegate methods to make sure the keyboard does what you want.

Continue reading →

Testing View Controller – Part 1

I’ve written a book to teach you how to write unit tests effectively. If you want to make your tests fast so you’ll actually run them and run them often to receive immediate feedback, check out Effective Unit Testing. You’ll develop the confidence that your change will not break existing features, and never have to worry about introducing regression. Write non-fragile unit tests that are assets, not liabilities. Use TDD to write testable code that drives feature development.

Now that you’ve tested the interactor and presenter in the Clean Swift VIP cycle. It’s time to finish up with the star of the show.

Drum roll please… View Controller

You’re going to finally take down the massive view controller. Massive leads to a massive post. So I’ll break this post into two parts:

In part 1, you’ll see the familiar setup and spy. You’ll then write tests for the expiration date picker to make sure a date is formatted as desired. We’ll diverge to look at the new invisible UI component and how it comes into play when testing view controllers. Finally, you’ll finish up by writing tests for the shipping method picker.

In part 2, you’ll write tests to make sure the keyboard behave as expected in all edge cases in which the text fields become first responder. You’ll also learn how to make running tests the same as running the app. Finally, you’ll test to make sure the pickers are configured properly.

Let’s get started.

Create the XCTestCase for the view controller

In Xcode, choose File -> New -> File, then select Test Case Class. Enter CreateOrderViewControllerTests for class. Make sure the CleanStoreTests target is checked. Click Create. The CreateOrderViewControllerTests.swift file is created.

The CreateOrderViewController’s input and output protocols are defined as follows:

Setup and Spy

With the interactor and presenter, setting up the subject under test is as simple as instantiating them, like CreateOrderInteractor() and CreateOrderPresenter(). In fact, the Clean Swift configurator creates them in the same way before hooking them up to the VIP cycle for real use. They are just POSOPlain Old Swift Object – with no parent class.

However, CreateOrderViewController inherits, either directly or indirectly, from UIViewController. It is loaded from the storyboard instead of created programmatically. This loading does a lot of things behind the scenes. Building the view hierarchy. Setting up the responder chain. Displaying the view on the screen. Among others.

Simply instantiating a view controller with CreateOrderViewController() doesn’t really fully set it up, ready to be used or tested.

But if you were to do all these things manually, you would need to dig deep into Apple’s documentation on view and view controller life cycles.

Fortunately, you don’t have to do that. You can just load it from the storyboard when you are running tests as if you are running the app.

You’ve seen similar code when you segue from one view controller to another. First, you get a bundle and a storyboard. And then call the instantiateViewControllerWithIdentifier() method with an identifier which you give to your view controller you create in the storyboard. It is almost always a good idea to set the identifier to the view controller class name.

But there are two very, very important things happening on the last line:

Continue reading →

Reader Question: If the business logic is inside of the Workers, then what’s the purpose of the interactor?

Marq asked a question on the role of the interactor and worker on my post about Testing Business Logic in Interactor.

I would be curious to see more about the worker concept as I am little confused by it’s purpose. The way that I interpreted it was more like a Service layer or Gateway (another boundary), which would retrieve objects (from a service, database, etc…) and then provide them to the interactor which would do something and pass the output back to the presenter. If the business logic is inside of the Workers, then what’s the purpose of the interactor? also where would code to a service or database then reside?

thanks,

That’s a good question. When you are adding your first worker to do some business logic, does it feel like you are just moving code from the interactor to the worker?

Does it then make the interactor unnecessary?

Why do you need an extra worker object to do stuff that your interactor already does?

Continue reading →

Testing Presentation Logic in Presenter

You learned how to test your business logic in the interactor using Clean Swift in my last post. Naturally, the flow of control leads us to the presenter today.

Specifically, you’ll be able to expand the role of a spy to make sure a method is invoked with the expected argument. You’ll also write a rather interesting test case to make sure a date is formatted correctly.

We’ll finish off by swapping out the spy with a mock. You’ll see how easy that is.

Create the XCTestCase for the presenter

In Xcode, choose File -> New -> File, then select Test Case Class. Enter CreateOrderPresenterTests for class. Make sure the CleanStoreTests target is checked. Click Create. The CreateOrderPresenterTests.swift file is created.

The CreateOrderPresenter’s input and output protocols are defined as follows:

Apply the Single Responsibility Principle (SRP) to Test Case

There is only one method to test. Yay! But look at the CreateOrderPresenter class’s presentExpirationDate() method. It seems to do quite a bit here.

As you recalled from the last post, formatting data is the presenter’s primary responsibility. The presentExpirationDate() method asks an NSDateFormatter object to return an NSDate in String representation.

The dateFormatter constant is set up outside of the method because we want to create it just once for efficiency reason. Later, we can reuse it for other formatting needs.

Even though it is not set up in the presentExpirationDate() method, you still want to test it in some way. But because it isn’t a boundary method, you don’t want to test it directly. Maybe NSDateFormatter is too slow, and you want to change the internal implementation in the future. So what do you do?

Continue reading →