Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need to write initializer for struct in Swift in order to use it in unit tests?

Tags:

xcode

ios

swift

I am trying to use a public struct

public struct Person {
  public let name: String
}

in a unit test (XCTest):

let person = Person(name: "Paul")

Test build fails with error:

'Person' cannot be constructed because it has no accessible initializers.

In order to build the test I need to write an initializer for the struct. Does not feel right because structs already have initializers. Does anyone have a better solution?

Xcode version 6.1.1 (6A2008a)

like image 692
Evgenii Avatar asked Dec 24 '14 10:12

Evgenii


2 Answers

The problem is that the automatically synthesised initialiser you get with a struct is synthesised as internal, meaning it can't be accessed from another module.

Your unit tests currently run in another module, so they can't see the initialiser. As Ben-G points out in his answer, this is addressed as of Swift 2.0 with the @testable attribute.

It's part of the general brokenness of unit testing in Swift projects. The unit testing module should have special access to the app modules, otherwise you have to add loads of access control baggage.

From the documentation:

Default Memberwise Initializers for Structure Types

The default memberwise initializer for a structure type is considered private if any of the structure’s stored properties are private. Otherwise, the initializer has an access level of internal.

As with the default initializer above, if you want a public structure type to be initializable with a memberwise initializer when used in another module, you must provide a public memberwise initializer yourself as part of the type’s definition.

like image 199
jrturton Avatar answered Oct 02 '22 15:10

jrturton


This is fixed in Swift 2.0 with the @testable attribute.

If you import your module into the tests with @testable the synthesized initializers will become visible to your tests.

You can find a brief intro to @testable here.

like image 38
Ben-G Avatar answered Oct 02 '22 14:10

Ben-G