mockingbird icon indicating copy to clipboard operation
mockingbird copied to clipboard

Don't mock unavailable methods

Open ss25sand opened this issue 4 years ago • 1 comments

New Issue Checklist

  • [x] I updated my Mockingbird framework and CLI to the latest version
  • [x] I searched for existing GitHub issues

Description

Mockingbird generate should not mock out methods annotated with @available(*, unavailable)

Generator Bugs

If the generator produces code that is malformed or does not compile, please provide:

  1. A minimal example of the original source
class CustomView: WKWebView {
    public init(frame: CGRect) {
        // ...
    }
    @available(*, unavailable)
    public required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
  1. The actual mocking code generated
public enum InitializerProxy {
    public static func initialize(`frame`: CGRect, __file: StaticString = #file, __line: UInt = #line) -> CustomViewMock {
      let mock: CustomViewMock = CustomViewMock(frame: `frame`)
      mock.sourceLocation = SourceLocation(__file, __line)
      return mock
    }

    @available(*, unavailable)
    public static func initialize(`coder` `aDecoder`: NSCoder, __file: StaticString = #file, __line: UInt = #line) -> CustomViewMock? {
      let mock: CustomViewMock? = CustomViewMock(coder: `aDecoder`)
      mock?.sourceLocation = SourceLocation(__file, __line)
      return mock
    }
  }
  1. The expected mocking code that should be generated (or a description)
public enum InitializerProxy {
    public static func initialize(`frame`: CGRect, __file: StaticString = #file, __line: UInt = #line) -> CustomViewMock {
      let mock: CustomViewMock = CustomViewMock(frame: `frame`)
      mock.sourceLocation = SourceLocation(__file, __line)
      return mock
    }
  }

If the generator is not producing code or crashing, please provide logging output from the Run Script Phase. See Debugging the generator for more information.

error: 'init(coder:)' is unavailable
      let mock: CustomViewMock? = CustomViewMock(coder: `aDecoder`)
                                  ^~~~~~~~~~~~~~
note: 'init(coder:)' has been explicitly marked unavailable here
  public required init?(`coder` `aDecoder`: NSCoder) {
                  ^
error: 'init(coder:)' is unavailable
    super.init(coder: `aDecoder`)
          ^~~~
note: 'init(coder:)' has been explicitly marked unavailable here
    public required init?(coder aDecoder: NSCoder) {
                    ^

Framework Bugs

Please provide a minimal example of your testing code, including any errors.

Environment

  • Mockingbird CLI version (mockingbird version) --> Using Mockingbird v0.17.0
  • Xcode and macOS version (are you running a beta?) --> XCode Version 12.5.1
  • Swift version (swift --version) --> Apple Swift version 5.4.2
  • Installation method (CocoaPods, Carthage, from source, etc) --> CocoaPods
  • Unit testing framework (XCTest, Quick + Nimble, etc) --> XCTest
  • Does your project use .mockingbird-ignore? No
  • Are you using supporting source files? Yes

ss25sand avatar Aug 23 '21 18:08 ss25sand

Thanks for flagging, Saman. Although not ideal, one workaround is to use compilation directives to gate an available and unavailable variant of the method.

class Foo {
  #if TEST
    func foobar() { /* ... */ }
  #else
    @available(*, unavailable)
    func foobar() { /* ... */ }
  #endif
}

andrewchang-bird avatar Aug 24 '21 17:08 andrewchang-bird