typealiased / mockingbird

A Swifty mocking framework for Swift and Objective-C.

Home Page:https://mockingbirdswift.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Failing to infer mocked type

paiv opened this issue · comments

New Issue Checklist

Description

Inferred return type of mock() is not usable.

Generator Bugs

$ mockingbird generate \
--only-protocols \
--disable-cache \
--targets 'Sample' \
--outputs "${SRCROOT}/MockingbirdMocks/SampleMocks.generated.swift"
  1. A minimal example of the original source
protocol Bird {
  func fly()
}
  1. The actual mocking code generated
//
//  SampleMocks.generated.swift
//  Sample
//
//  Generated by Mockingbird v0.11.0.
//  DO NOT EDIT
//

@testable import Mockingbird
@testable import Sample
import Foundation
import Swift

private var genericTypesStaticMocks = Mockingbird.Synchronized<[String: Mockingbird.StaticMock]>([:])

// MARK: - Mocked Bird

public final class BirdMock: Sample.Bird, Mockingbird.Mock, BirdAbstractMockType {
  static let staticMock = Mockingbird.StaticMock()
  public let mockingContext = Mockingbird.MockingContext()
  public let stubbingContext = Mockingbird.StubbingContext()
  public let mockMetadata = Mockingbird.MockMetadata(["generator_version": "0.11.0", "module_name": "Sample"])
  public var sourceLocation: Mockingbird.SourceLocation? {
    get { return stubbingContext.sourceLocation }
    set {
      stubbingContext.sourceLocation = newValue
      BirdMock.staticMock.stubbingContext.sourceLocation = newValue
    }
  }

  fileprivate init(sourceLocation: Mockingbird.SourceLocation) {
    Mockingbird.checkVersion(for: self)
    self.sourceLocation = sourceLocation
  }

  // MARK: Mocked `fly`()

  public func `fly`() -> Void {
    let invocation: Mockingbird.Invocation = Mockingbird.Invocation(selectorName: "`fly`() -> Void", arguments: [])
    mockingContext.didInvoke(invocation)
    let implementation = stubbingContext.implementation(for: invocation, optional: true)
    if let concreteImplementation = implementation as? () -> Void {
      concreteImplementation()
    } else {
      (implementation as? () -> Void)?()
    }
  }

  public func `fly`() -> Mockingbird.Mockable<Mockingbird.MethodDeclaration, () -> Void, Void> {
    let invocation: Mockingbird.Invocation = Mockingbird.Invocation(selectorName: "`fly`() -> Void", arguments: [])
    return Mockingbird.Mockable<Mockingbird.MethodDeclaration, () -> Void, Void>(mock: self, invocation: invocation)
  }
}

public protocol BirdAbstractMockType {}

/// Initialize a protocol mock of `Sample.Bird`.
public func mock(_ type: Sample.Bird.Protocol, file: StaticString = #file, line: UInt = #line) -> BirdAbstractMockType {
  return BirdMock(sourceLocation: SourceLocation(file, line))
}

/// Initialize a protocol mock of `Sample.Bird`.
public func mock<__ReturnType: BirdAbstractMockType>(_ type: Sample.Bird.Protocol, file: StaticString = #file, line: UInt = #line) -> __ReturnType {
  return BirdMock(sourceLocation: SourceLocation(file, line)) as! __ReturnType
}

/// Create a dummy object of `Sample.Bird`.
public func dummy(_ type: Sample.Bird.Protocol, file: StaticString = #file, line: UInt = #line) -> BirdMock {
  return BirdMock(sourceLocation: SourceLocation(file, line))
}

/// Initialize a protocol mock of `Sample.Bird`.
@available(swift, obsoleted: 3.0, renamed: "dummy", message: "Store the mock in a variable of type 'BirdMock' or use 'dummy(Bird.self)' to create a non-mockable dummy object")
public func mock<__ReturnType>(_ type: Sample.Bird.Protocol) -> __ReturnType { fatalError() }
  1. The expected mocking code that should be generated (or a description)

Not sure yet.

Framework Bugs

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

func testBird() {
    let bird = mock(Bird.self)

    (bird as Bird).fly()
    // 'BirdAbstractMockType' is not convertible to 'Bird'; did you mean to use 'as!' to force downcast?

    verify(bird.fly()).wasCalled()
    // Value of type 'BirdAbstractMockType' has no member 'fly'
}

Environment

  • Mockingbird CLI version 0.11.0
  • Xcode 11.4 and macOS 10.15.4
  • Swift version Apple Swift version 5.2 (swiftlang-1103.0.32.1 clang-1103.0.32.29)
  • Installation method CocoaPods

This is unfortunate, and breaks README promise:

let bird: BirdMock = mock(Bird.self)  // The concrete type is `BirdMock`
let inferredBird = mock(Bird.self)    // but type inference also works

Thanks for reporting, this was an oversight on my part. Seems like there is no easy fix, so I’ll revert the initializer changes in 0.11.1.

As a workaround, declaring explicit type annotations using the concrete mock type, e.g. SomeTypeMock, should make the compiler happy again.