TestsTested | ✗ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Sep 2016 |
Maintained by Orta Therox, Ash Furrow.
Forgeries is a library that makes unit testing iOS applications easier. UIKit has lots of limitations that make sense in production code, but make testing difficult. Forgeries fixes that problem.
Currently, the library provides testing replacements for:
These can be used with Dependency Injection, or by using OCMock to replace global singletons.
The following are Forgeries' subclasses for gesture recognizers.
These subclasses keep track of the number of times they've invoked their targets' actions; a handy interface to UIGestureRecognizer
is provided:
@interface UIGestureRecognizer (Forgeries)
- (void)invoke;
@end
ForgeriesUserDefaults
is a class which is API compatible with NSUserDefaults. It has a few extra tools that make it useful for testing:
[ForgeriesUserDefaults defaults:@{}]
for setting up defaults from a dictionarylastSetKey
, lastRequestedKey
and whether it has been synchronised via hasSyncronised
[NSUserDefaults standardUserDefaults]
when OCMock is available in the test targetNote this class isn't yet a subclass of NSUserDefaults, and so cannot be DI'd in to Swift classes.
ForgeriesFileManager
is still new, so it's API is relatively limited as we find more use cases for it.
A quick API for setting up defaults from a dictionary
ForgeriesFileManager *fm = [ForgeriesFileManager withFileStringMap:@{
@"/docs/EchoTest.json" : @{ @"updated_at" : @"2001-01-23" },
@"/app/EchoTest.json": @{ @"updated_at" : @"1985-01-23" },
@"/docs/VERSION" : @"1.0.1"
}];
This API will automatically convert dictionaries to raw JSON data, or let you create files with text
[NSFileManager defaultManager]
when OCMock is available in the test targetYou can stub the trait collections for UIView
and UIViewController
, the two UITraitEnvironments
that we currently support.
[subject stubHorizontalSizeClass:UIUserInterfaceSizeClassRegular];
Nothing to out of the normal here, you can create a ForgeriesApplication
which is a UIApplication subclass for DI-ing a test.
The trick is to use Forgeries in testing only. A great way to do this is via Dependency Injection. This means injecting a dependency into an instance, instead of having that instance create the dependency itself, or access shared state. Let's take a look at an example.
Say you're testing MyViewController
, you'd use lazy loading for your recognizer.
@interface MyViewController ()
@property (nonatomic, strong) UITapGestureRecognizer *recognizer;
@end
@implementation MyViewController
...
- (UITapGestureRecognizer *)recognizer {
if (_recognizer == nil) {
_recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGestureRecognizer:)];
}
return _recognizer;
}
...
What we need to do is set that property before it is lazily loaded. Here's our testing code:
MyViewController *subject = /* Instantiate somehow */
ForgeryTapGestureRecognizer *recognizer = [[ForgeryTapGestureRecognizer alloc] initWithTarget:subject action:@selector(handleGestureRecognizer:)];
subject.recognizer = recognizer;
/* Optionally, set the testing_location and testing_velocity properties on recognizer. */
[recognizer invoke];
expect(subject).to( /* have done something, whatever it is you're testing for */ );
If you're interested in dependency injection, we strongly recommend watching this talk from Jon Reid
Requires iOS 7 or higher.
Forgeries is available through CocoaPods. To install it, simply add the following line to your Podfile under the unit testing target:
target 'MyApp_Tests' do
inherit! :search_paths
pod 'Forgeries'
...
end
That will import the core functionality, not including mock stuff. If you want to use Forgeries with OCMock, use the following instead:
pod 'Forgeries/Mocks'
Now import the library in your unit tests.
import Forgeries
@import Forgeries;
// or #import <Forgeries/Forgeries.h>
Forgeries is available under the MIT license. See the LICENSE file for more info.