mockingbird icon indicating copy to clipboard operation
mockingbird copied to clipboard

any keyword seems not supported

Open paul1893 opened this issue 1 year ago • 0 comments

New Issue Checklist

Overview

Generating a mock that have properties with Swift any keyword seems to fail.

Example

  1. A minimal example of the original source

For example let's say we have a class like this:

public class CodableFileManager<T: Codable & Equatable> {
    private let generator: any GeneratorProtocol

    public init(
        generator: any GeneratorProtocol
    ) {
        self.generator = generator
    }

func doSomeStuff() {}

Trying to use a mock of the class in tests like this:

codableFileManager = mock(CodableFileManager<MyCodableAndEquatableStruct>.self).initialize(generator: generator)

produces a generation error as below.

  1. The actual mocking code generated
// MARK: - Mocked CodableFileManager
public final class CodableFileManagerMock<T: Codable & Equatable>: EasyKit.CodableFileManager<T>, Mockingbird.Mock {
  typealias MockingbirdSupertype = EasyKit.CodableFileManager<T>
  public static var mockingbirdContext: Mockingbird.Context { return mkbGenericStaticMockContext.resolve(["CodableFileManagerMock<T>", Swift.ObjectIdentifier(T.self).debugDescription]) }
  public let mockingbirdContext = Mockingbird.Context(["generator_version": "0.20.0", "module_name": "EasyKit"])

  public enum InitializerProxy {
    public static func initialize(`generator`: any GeneratorProtocol, __file: StaticString = #file, __line: UInt = #line) -> CodableFileManagerMock<T> {
      let mock: CodableFileManagerMock<T> = CodableFileManagerMock<T>(generator: `generator`)
      mock.mockingbirdContext.sourceLocation = SourceLocation(__file, __line)
      return mock
    }
  }

  // MARK: Mocked `doSomeStuff`()
  public override func `doSomeStuff`() -> Void {
    return self.mockingbirdContext.mocking.didInvoke(Mockingbird.SwiftInvocation(selectorName: "`doSomeStuff`() -> Void", selectorType: Mockingbird.SelectorType.method, arguments: [], returnType: Swift.ObjectIdentifier((Void).self))) {
      self.mockingbirdContext.recordInvocation($0)
      let mkbImpl = self.mockingbirdContext.stubbing.implementation(for: $0)
      if let mkbImpl = mkbImpl as? () -> Void { return mkbImpl() }
      for mkbTargetBox in self.mockingbirdContext.proxy.targets(for: $0) {
        switch mkbTargetBox.target {
        case .super:
          return super.`doSomeStuff`()
        case .object(let mkbObject):
          guard var mkbObject = mkbObject as? MockingbirdSupertype else { break }
          let mkbValue: Void = mkbObject.`doSomeStuff`()
          self.mockingbirdContext.proxy.updateTarget(&mkbObject, in: mkbTargetBox)
          return mkbValue
        }
      }
      if let mkbValue = self.mockingbirdContext.stubbing.defaultValueProvider.value.provideValue(for: (Void).self) { return mkbValue }
      self.mockingbirdContext.stubbing.failTest(for: $0, at: self.mockingbirdContext.sourceLocation)
    }
  }

  public func `doSomeStuff`() -> Mockingbird.Mockable<Mockingbird.FunctionDeclaration, () -> Void, Void> {
    return Mockingbird.Mockable<Mockingbird.FunctionDeclaration, () -> Void, Void>(context: self.mockingbirdContext, invocation: Mockingbird.SwiftInvocation(selectorName: "`doSomeStuff`() -> Void", selectorType: Mockingbird.SelectorType.method, arguments: [], returnType: Swift.ObjectIdentifier((Void).self)))
  }

  // MARK: Mocked init(`generator`: any GeneratorProtocol)
  public required override init(`generator`: any GeneratorProtocol) {
    super.init(generator: `generator`)
    self.mockingbirdContext.mocking.didInvoke(Mockingbird.SwiftInvocation(selectorName: "init(`generator`: any GeneratorProtocol)", selectorType: Mockingbird.SelectorType.method, arguments: [Mockingbird.ArgumentMatcher(`generator`)], returnType: Swift.ObjectIdentifier((Void).self)))
  }

  public func initialize(`generator`: @autoclosure () -> any GeneratorProtocol) -> Mockingbird.Mockable<Mockingbird.FunctionDeclaration, (any GeneratorProtocol) -> Void, Void> {
    return Mockingbird.Mockable<Mockingbird.FunctionDeclaration, (any GeneratorProtocol) -> Void, Void>(context: self.mockingbirdContext, invocation: Mockingbird.SwiftInvocation(selectorName: "init(`generator`: any GeneratorProtocol)", selectorType: Mockingbird.SelectorType.method, arguments: [Mockingbird.resolve(`generator`)], returnType: Swift.ObjectIdentifier((Void).self)))
  }
}

/// Returns an abstract mock which should be initialized using `mock(CodableFileManager.self).initialize(…)`.
public func mock<T: Codable & Equatable>(_ type: EasyKit.CodableFileManager<T>.Type, file: StaticString = #file, line: UInt = #line) -> CodableFileManagerMock<T>.InitializerProxy.Type {
  return CodableFileManagerMock<T>.InitializerProxy.self
}
image

Expected Behavior

The generated file should compile.

Environment

  • Mockingbird CLI version: 0.20.0
  • Xcode and Swift version: XCode 13.4.1 / Swift 5.6.1
  • Package manager: CocoaPods
  • Unit testing framework: XCTest
  • Custom configuration
    • [x] Mockingbird ignore files
    • [x] Supporting source files

paul1893 avatar Sep 01 '22 10:09 paul1893