1

Recently I spent quite some time to figure it out the issue with my unit test. The error that I saw in my unit test is :

Ambiguous type name 'AssetIdentifier' in 'UIImage'

This is the complete code :

import XCTest
import module
@testable import module

class VoucherOptionsViewControllerTests: XCTestCase {
    lazy var result = ""

    class VoucherOptionsViewControllerMock: VoucherOptionsViewController {

        var result = ""

        override func showOverlayView(title: String, message: String, assetIdentifier: UIImage.AssetIdentifier) {
            self.result = "lalalala"
        }
    }
}

AssetIdentifier is an enum in UIImage extension

I tried the suggestion listed in:

Ambiguous type name error

However, it returns me with a different error on the controller:

'AssetIdentifier' is inaccessible due to 'internal' protection level

I've tried to clean and rebuild but it returns the same error.

mokagio
  • 16,391
  • 3
  • 51
  • 58
surga
  • 1,436
  • 21
  • 25

2 Answers2

5

I think your issue lays in the double import of the module module.

import module
@testable import module

By importing it twice you give the compiler two (identical) versions of every type and function defined in module. That's why it's complaining about the ambiguity of AssetIdentifier, there's two of those and it doesn't know which to pick.

The right thing to do would be to remove import module though.

The @testable import statement allows you to import a module in your test target and to gain access to the types and functions defined internal as well as public.

When you add the @testable attribute to an import statement for a module compiled with testing enabled, you activate the elevated access for that module in that scope. Classes and class members marked as internal or public behave as if they were marked open. Other entities marked as internal act as if they were declared public.

Source.

If you do that you'll see that you won't have ambiguity issues and you won't need to move the UIImage extension in the test target. As @JonReid rightfully pointed out in his comment "Production code should remain in your production target".

Hope this helps.

mokagio
  • 16,391
  • 3
  • 51
  • 58
2

Although that thread does not give the real answer, it gives great clue about the issue. So the fix that I found is by removing :

@testable import module

I keep the UIImage extension in the test module so the compiler does not complain.

surga
  • 1,436
  • 21
  • 25
  • This is a workaround, not a fix. Production code should remain in your production target, and test code in your test target. Change your protection level instead. – Jon Reid Aug 26 '17 at 18:52
  • 1
    Thank you @JonReid. However, I believe by removing the `@testable` I didn't change the target in the UIImage extension or any other classes. The question is remain though why `@testable` causing compiler to complain that there is duplication in enum. Why it does not complain duplication in another class. If you can help me elaborate this one. Thank you. – surga Aug 27 '17 at 04:16
  • Could you add your extension source code to the question? – Jon Reid Aug 28 '17 at 00:12