简体   繁体   中英

Unit testing (Kiwi): Property is always nil in test after loadView and viewDidLoad are called

I am writing a unit test template project for my own reference's sake. This includes template code for all the basic tasks, such as verifying that a UILabel's text property is set as expected after viewDidLoad.

I have a storyboard with a ViewController with one UILabel. In viewDidLoad I set it's text. The test then asserts whether or not the text has been set as expected, but for some reason, the UILabel is always nil. Everything works as expected (thank god) when I run the app; a white view is shown with a label with the expected text.

I am using Kiwi as my test framework and Xcode v4.5.

Here's some code:

ViewController.h:

@property (strong, nonatomic) IBOutlet UILabel *myLabel;

ViewController.m:

- (void)viewDidLoad {
    myLabel.text = @"test";
}

ViewControllerTests.m:

ViewController *vc = [[ViewController alloc] init];

// create view in memory by calling view's getter
[vc view];

// set myLabel.text to "test"
[vc viewDidLoad];

[vc.myLabel shouldNotBeNil];
[[vc.myLabel.text should] equal:@"test"];

The above test fails, telling me that myLabel is nil.

This StackOverflow answer states that calling loadView will create the view hierarchy in memory and thereby prepare any subviews for use. According to the documentation , simply calling a ViewController view's getter will call loadView for you and create all views. Therefore, I find it extremely odd that myLabel = nil at the time of testing.

In your view controller, you are not assigning a value to self.myLabel .

self.myLabel = [[UILabel alloc] init];

This means self.myLabel has a nil value, so the following sequence occurs: [self myLabel] returns nil, [nil setText:@"test"] does nothing. All of this is standard behavior.

When you load the view controller from the nib or storyboard, the label is assigned according to how the outlets are drawn in IB, but calling ViewController *vc = [[ViewController alloc] init] does not loading the nib or storyboard.


Update

After re-reading my post, I think I left the wrong impression.

You need to load from a nib or storyboard, not add self.myLabel = [[UILabel alloc] init] .

To load from a nib, use -initWithNibName:bundle: instead of -init . To load from a storyboard, first load the storyboard use +[UIStoryboard storyboardWithName:bundle:] , then load the view controller from the storyboard using -[UIStoryboard instantiateViewControllerWithIdentifier:] .

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