简体   繁体   中英

Is it possible to instantiate a View Controller from a Storyboard for Kiwi Testing

I'm in for testing some code within a ViewController (that certain controls are active depending on the state of certain UISwitches etc) and decided to go for Kiwi for it, since we are using it for some other low-level logic testing.

My expectation is to run tests like this:

__block AViewController *aVC;

it(@"(tokenTextField) should be hidden if the token switch is set to off", ^{
    lvC.useTokenSwitch.on = false;
    [[theValue(aVC.tokenTextField.hidden) should] equal:theValue(YES)];
});

My problem is with the initialisation of the AViewController. If I did:

aVC = [[AViewController alloc] initWithNibName:@"aViewController" bundle:nil];

I would be getting a "AViewController" without any controls initialised, so I'd have to init each of them manually.

So I have tried obtaining the AViewController doing this:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
aVC = [storyboard instantiateViewControllerWithIdentifier:@"AViewController"];

Yet this results in an error message:

NSInvalidArgumentException "Could not find a storyboard named 'MainStoryboard' in bundle NSBundle </Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk/Developer/usr/bin> (loaded)" raised

I have included the MainStoryboard in my testing target, and also included it in "Build Phases" -> "Copy Bundle Resources" and still nothing.

So I am wondering if it is even possible to instantiate a ViewController from a Storyboard in a Kiwi Testing Target? (As I haven't seen any examples of it anywhere).

Is my approach wrong and I should be mocking the ViewController?

Am I missing something to be included in the test target?

The problem is that you're passing nil for your bundle. You can see in the error message the bundle it's using. In a unit test, you probably want to do something like this:

Class viewControllerClass = [myViewController class];

NSString *className = NSStringFromClass(viewControllerClass);
NSBundle *classBundle = [NSBundle bundleForClass:viewControllerClass];

MyViewController *viewController =
[[MyViewController alloc] initWithNibName:className
                                   bundle:classBundle];

By looking for the bundle that contains your view controller's class, you'll also get the nib file for it.

For storyboards, the code is similar:

Class viewControllerClass = [myViewController class];

NSString *className = NSStringFromClass(viewControllerClass);
NSBundle *classBundle = [NSBundle bundleForClass:viewControllerClass];

UIStoryboard *storyboard =
[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:classBundle];

MyViewController *viewController =
[storyboard instantiateViewControllerWithIdentifier:className];

(This all assumes that your nib names and storyboard identifiers match the class names. If they don't, change it.)

"AViewController" without any controls initialised

is because the initialisation of all these controls is belong to view, you need to call [viewController loadView] to init the UI component.

if you also use viewDidLoad func to init some UI component, you must call [viewController view] to trigger viewDidLoad function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM