MVVM-C Architecture with Dependency Injection + Testing _ by Steven Curtis _ Medium
MVVM-C Architecture with Dependency Injection + Testing _ by Steven Curtis _ Medium
You have 1 free member-only story left this month. Sign up for Medium and get an extra one.
Member-only story
273 2
I’ve been using MVVM-C for quite some time. I’m sure you (probably, I don’t
know you) agree that by abstracting the navigation away from the main
MVVM architecture code gives you the opportunity for testing. Great!
What if you have multiple dependencies? How are these going to be injected
into your…wait.. where…what?
This article has been developed using Xcode 11.4.1, and Swift 5.2.2
Prerequisites:
You will be expected to be aware how to make a Single View
Application in Swift.
Terminology:
Factory Pattern: A design pattern where an object is created without
exposing the creation logic to the client. The factory pattern lets a class defer
instantiation to subclasses.
The Problem
MVVM-C helps with separation of concerns, and allows testing and
implementation to be…much better than MVC. Now, nothing is perfect, but
it is perfectly possible to have a variety of dependencies which can lead to
large and unwieldy initializers.
One possible solution to this is use of the Factory Pattern, and the use of
Dependency Injection to test the relevant classes. This particular article is
written with the views programmatically defined, avoiding Storyboards in
the entire project, and neatly overriding loadview().
The Example
The idea of this article is to have a basic skeleton for the MVVM-C
architecture. There are few around, particularly coded in Swift and even
fewer making an attempt at testing.
You’re probably working in a shop where they demand 80% test coverage —
and this article and the accompanying repo isn’t quite there (this example
isn’t promised to be production ready), however it is a very good start for a
developer to build on.
Initialize the ViewModel with the fetched data (or instruct the
ViewModel to handle a failed network call)
The Implementation
One of the best ways to explore the implementation is do download the files
to your machine and take a look. Give me a nice star when you’re there (if
you can).
The coordinator
This is at the heart of the matter, because the coordinator controls the flow
of the App. If a UIViewController wishes to move to another UIViewController
The ProjectCoordinator has knowledge of just the factory class, which it uses
to create the InitialViewController instance which is then pushed on the
UINavigationController stack. The reference to navigationController is weak
to prevent a retain cycle as the UIViewController instance has a reference to
the ProjectCoordinator .
The Factory
The Dependency Factory class lets us inject services. This example has a
‘fake HTTPManager based upon my basic http manager class at it’s heart,
although I’m sure you have your own solution for making network calls
(don’t feel like I’m bullying you into this).
The dependency factory creates these artifacts that will be used to create the
objects that our App requires.
The view model creates the model from here when the network model
returns data from the Endpoint API.
The UIViewController classes are responsible for the UIView classes, and
since in this implementation they have no dependencies these are created
within the UIViewController .
The initializer
class.
Equally, the view controller has viability of the view model class, and it is the
viewmodel classes that are used for network calls in this implementation.
You might well use this to store something like user details (obtained by an
API), or whatever. The choice is yours.
Unfortunately there isn’t much to learn from this class, but for completion’s
sake here is the code:
Testing
This article is not about testing specifically, but does contain tests and mocks
partly because there is so little out there in existing articles.
To keep this article readable (or at least approaching readable) I’ve kept the
implementation details of these tests to the repo. To access the code hop
over to the repo and press download. You can then read through the files,
but below is the explanation of the same.
Unit testing
ViewModels
UIViews
The views should not usually be unit tested. What are you going to check?
The positions of the view in a container that doesn’t exist?
The coordinator
We can mark a test function with throws, and any exception would cause the
test to fail. This can be used in conjunction with a guard statement a mock
for UINavigationController to ensure the correct View Controller is pushed
onto the UINavigationController (well, a mock of UINavigationController )
stack.
The Factory
It doesn’t make any sense to test the dependency factory, as it is this class
that is replaced for the tests. FactoryTests is simply empty.
Conclusion
I hope this article has helped you out, going through the relevant classes that
enable you to create a MVVM-C implementation.
If you’ve been using MVC I appreciate this might seem like a change and,
yes, well it is.
However having different methods of producing your App will only help in
the long run, and I hope that this article has really helped you out.
273 2
26K Followers
stevecurtis.me
Top iOS and Swift Developer WWDC 2023: What’s New In Swift
Interview Questions for 2023 It’s getting great!
iOS Job Hunters Get Ready
132 235 1
121 95 2
126 1 149 6
Lists
· 6 min read · Dec 29, 2022 · 4 min read · Dec 31, 2022
176 2 136
3.9K 84 226 2
See more recommendations
Help Status Writers Blog Careers Privacy Terms About Text to speech Teams