18

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)

1
  • I think the problem is: as 'name' is a constant, you have to initialize a value for it. Commented Dec 24, 2014 at 10:43

2 Answers 2

43

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Also applies to "support code" added to the Sources dir in a new 6.3 playground. Continuing the theme of playgrounds being continually just shy of useful.
20

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.

1 Comment

This interestingly was the same solution to using structs in Playground. Nice find.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.