# Testing internal classes in Obj-C module

**URL:** <https://forums.swift.org/t/testing-internal-classes-in-obj-c-module/64110>\
**Category:** Package Manager\
**Tags:** objective-c, packagemanager\
**Created:** [March 31, 2023, 8:15pm UTC](https://forums.swift.org/t/testing-internal-classes-in-obj-c-module/64110 "2023-03-31T20:15:04Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![atreat](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/atreat/32/12425_2.png) [@atreat](https://forums.swift.org/u/atreat)\
**Post date:** [March 31, 2023, 8:15pm UTC](https://forums.swift.org/t/testing-internal-classes-in-obj-c-module/64110/1 "2023-03-31T20:15:04Z")

</div>

I'm switching an old Objective-C project into the SPM project structure. Have questions about testing internal classes of a module.

Given an example of two targets:

```swift
// Package.swift
.target("MyTarget", cSettings: [ 
    .headerSearchPath("MyInternalStuff/MyInternalClass.h")
]),
.testTarget("MyTargetTests", dependencies: ["MyTarget"])

```

I have a test file inside the `MyTargetTests` where I can get access to the public classes of `MyTarget` using the `@import MyTarget`.

```plaintext
#import <XCTest/XCTest.h>

@import MyTarget;

@interface MyInternalClassTests : XCTestCase

@property (nonatomic, retain) MyPublicClass myPublicObject; // works great

@property (nonatomic, retain) MyInternalClass myInternalObject; // Unknown type name 'MyInternalClass'

@end

```

In Swift, this would be accomplished with `@testable import MyTarget`. I'm wondering if I should be using a different mechanism to import in my testTarget such that I have access to internal classes?

I've tried the following to no avail:

```plaintext
#import "MyInternalClass.h"

#import "MyTarget/MyInternalClass.h"

#import <MyTarget/MyInternalClass.h>

```

Wondering if anyone has had any luck testing module internals in an objective-c target and test target.

---

<div class="post-metadata">

**Author:** ![atreat](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/atreat/32/12425_2.png) [@atreat](https://forums.swift.org/u/atreat)\
**Post date:** [March 31, 2023, 8:24pm UTC](https://forums.swift.org/t/testing-internal-classes-in-obj-c-module/64110/2 "2023-03-31T20:24:13Z")

</div>

I wanted to check if/how this would work inside a test target implemented in Swift.

Short answer is it appears it doesn't.

I added a new testTarget written in swift to try this out:

```swift
// Package.swift
.target("MyTarget", cSettings: [ 
    .headerSearchPath("MyInternalStuff/MyInternalClass.h")
]),
.testTarget("MyTargetTests", dependencies: ["MyTarget"]),
.testTarget("MyTargetTestsSwift", dependencies: ["MyTarget"])

```

In this `MyTargetTestsSwift` I have a test class:

```swift

import XCTest

@testable import MyTarget

final class MyTargetInternalClass Tests: XCTestCase {

    func testExample() throws {
        let publicObj = MyTargetPublicClass()
        print(publicObj)

        let internalObj = MyTargetInternalClass() // Cannot find 'MyTargetInternalClass' in scope. Quick fix "Import MyTarget"
        print(internalObj)
    }

}

```

What is really odd is Xcode will tell me to import the module that it already has imported. I can confirm because the `MyTargetPublicClass` is printed fine if I comment out the lower half of the test.

* * *

I feel like the only workaround would be to get really funky with the headerSearchPaths of my test target to include all the sources from the main target. This doesn't feel like a good way to do this though.

---

<div class="post-metadata">

**Author:** ![tgoyne](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@tgoyne](https://forums.swift.org/u/tgoyne)\
**Post date:** [March 31, 2023, 8:50pm UTC](https://forums.swift.org/t/testing-internal-classes-in-obj-c-module/64110/3 "2023-03-31T20:50:55Z")

</div>

We achieve this by putting the private headers we want to expose in the public headers dir, and then use a [custom modulemap](https://github.com/realm/realm-swift/blob/master/include/module.modulemap) to divide the headers into modules. This results in `import Realm` importing only the headers which are part of the umbrella header, and `import Realm.Private` imports the private headers as well. This works when importing from both obj-c and Swift.

---

<div class="post-metadata">

**Author:** ![atreat](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/atreat/32/12425_2.png) [@atreat](https://forums.swift.org/u/atreat)\
**Post date:** [April 2, 2023, 2:25am UTC](https://forums.swift.org/t/testing-internal-classes-in-obj-c-module/64110/4 "2023-04-02T02:25:16Z")

</div>

Thanks for the quick response. I was able to accomplish what I needed using a custom modulemap and an inner module.

I didn't need to put the private headers into the `include` directory of the module, but my `header` definitions are relative paths that use `..` to escape. Not sure if this is a good way to do it. I like being able to keep my public/private headers separate though.

```swift
module MyTarget {
    export *
    umbrella "."

    explicit module Internal {
        header "../MyInternalStuff/MyInternalClass.h"
    }
}

```

This allows me to do the following to import internal classes in the testTarget:

```swift
@import MyTarget.Internal;

```
