1

I am just getting into unit testing in Xcode, so I decided to play a bit with the default test target that gets created with any of Xcode's project templates.

As a start, I decided to perform a very basic test to see whether the AppDelegate instance's window property (of type UIWindow?) is actually set.

This is my test code:

import UIKit
import XCTest

import Sample   // This is the App target (app is called "Sample")

class SampleTests: XCTestCase
{
    override func setUp(){
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown(){
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testExample(){
        // This is an example of a functional test case.

        if let delegate = UIApplication.sharedApplication().delegate{

            if let myDelegate = delegate as? AppDelegate {

                if let window = myDelegate.window {

                    XCTAssert(true, "Pass")
                }
                else{
                    XCTFail("App Delegate Has No Window")
                }
            }
            else{
                XCTFail("Application Delegate Object Is of The Wrong Type")
            }
        }
        else{
            XCTFail("Application Delegate Not Present")
        }
    }
}

At first, I couldn't build the test target because the AppDelegate class was not accessible. I tried two approaches, with different results:

  1. If I mark both my AppDelegate class and all its properties/methods as public, the test builds with no errors and succeeds (i.e., window optional is not nil).

  2. If, instead, I mark class, properties and methods of AppDelegate as internal, but modify the source file's target membership to also belong to the test target (not just the app target), the test builds with no errors but fails ("Application Delegate Object Is of The Wrong Type", i.e., the conditional cast to AppDelegate type fails).

Looks as though with the second approach, a different application delegate is present at runtime. Does anybody know what is happening?

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
  • 1
    actually there is different app delegate for your project and for your test project.... – LC 웃 Aug 05 '15 at 07:55
  • 1
    @Nicolas anish is right, check rintaro's answer from http://stackoverflow.com/questions/26946677/uiapplication-sharedapplication-delegate-as-appdelegate-causes-exc-bad-access – Bhushan B Aug 05 '15 at 08:01
  • @Bhushan I guess that means my question is a duplicate. Exact same problem, exact same solution. Still not very clear on why AppName.AppDelegate and AppNameTests.AppDelegate are different classes, but I guess that's how the test runtime environment is set up... – Nicolas Miari Aug 05 '15 at 08:21

1 Answers1

1

Actually there is a single App Delegate file in the project.But when you add AppDelegate.swift to the tests target members,then your Test's App Delegate Class will be different than the AppDelegate class.

 if let delegate = UIApplication.sharedApplication().delegate{

The above If statement tries to returns project delegate instance different than you are trying to Cast.

   if let myDelegate = delegate as? AppDelegate  

And hence casting to AppDelegate doesnot succeed.So,you get always fail as

 XCTFail("Application Delegate Object Is of The Wrong Type")

UPDATED:

i wrote some few test cases to know the exact problem:

1)Test Case to find out if AppDelegate is nil. (Passes)

 if let delegate = UIApplication.sharedApplication().delegate{

            XCTAssertNotNil(delegate, "not nil")

2)So,next test is below (Fails)

XCTAssertNotNil(delegate as? AppDelegate, "not nil")

This test case fails..So its sure there was problem in casting.

LC 웃
  • 18,888
  • 9
  • 57
  • 72
  • Thanks, that's what I was suspecting. However, the wording of your answer doesn't make clear _why_. The answer pointed to by @Bhushan contains a more illumintaing sentence: "When you do that, AppName.AppDelegate and AppNameTests.AppDelegate becomes different classes.". – Nicolas Miari Aug 05 '15 at 08:18
  • actually i too hit few test cases as of updated answer and concluded what was wrong..i will update the answer later on... – LC 웃 Aug 05 '15 at 08:30
  • 1
    Thanks again. I have accepted your answer, but also marked my question as duplicate. Feel free to add any further information to your answer, – Nicolas Miari Aug 05 '15 at 08:33