Skip to content

tesum/TSMockableMacros

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MockableMacros


💻 🤲 🌓 ⚒️
SPM Package for easily mocking out objects using macros
It's as simple as adding the @Mockable attribute to your protocol, and then use new class.

Usage

Just add the attribute to your protocol, as here:

  @Mockable
  public protocol CarProtocol {
    var isStarted: Bool { get set }
  
    func startEngine(full: Bool) async throws -> Bool
    func startEngine(turnOn: Bool, completion: @escaping () -> Void)
    func startEngine(completion: @escaping (Int) -> Void)
    func startEngine(result: Int, completion: @escaping (Result<Int, Never>) -> Void)
  }

This will generate the CarProtocolMockable class, which contains variables and functions with additional variables for ease of testing.

Example
public final class CarProtocolMockable: CarProtocol {

public init() {
}

// MARK: - Variables

public var isStarted: Bool {
    get {
        return underlyingIsStarted
    }
    set(value) {
        underlyingIsStarted = value
    }
}

public var underlyingIsStarted: Bool!

// MARK: - Functions

// `startEngineFull` mock block

public var startEngineFullCallsCount: Int = 0
public var startEngineFullCalled: Bool {
  return startEngineFullCallsCount > 0
}
public var startEngineFullError: MockError?
public var startEngineFullResponse: Bool?

public func startEngine(full: Bool) async throws -> Bool {
  startEngineFullCallsCount += 1
  if let error = startEngineFullError {
      throw error
  }
  return startEngineFullResponse!
}

// `startEngineTurnOnCompletion` mock block

  public var startEngineTurnOnCompletionCallsCount: Int = 0
public var startEngineTurnOnCompletionCalled: Bool {
  return startEngineTurnOnCompletionCallsCount > 0
}

public var startEngineTurnOnCompletionResponse: ((Bool, @escaping () -> Void) -> Void)?

public func startEngine(turnOn: Bool, completion: @escaping () -> Void) {
  startEngineTurnOnCompletionCallsCount += 1

  startEngineTurnOnCompletionResponse?(turnOn, completion)
}

// `startEngineCompletion` mock block

  public var startEngineCompletionCallsCount: Int = 0
public var startEngineCompletionCalled: Bool {
  return startEngineCompletionCallsCount > 0
}

public var startEngineCompletionResponse: ((@escaping (Int) -> Void) -> Void)?

public func startEngine(completion: @escaping (Int) -> Void) {
  startEngineCompletionCallsCount += 1

  startEngineCompletionResponse?(completion)
}

// `startEngineResultCompletion` mock block

  public var startEngineResultCompletionCallsCount: Int = 0
public var startEngineResultCompletionCalled: Bool {
  return startEngineResultCompletionCallsCount > 0
}

public var startEngineResultCompletionResponse: ((Int, @escaping (Result<Int, Never>) -> Void) -> Void)?

public func startEngine(result: Int, completion: @escaping (Result<Int, Never>) -> Void) {
  startEngineResultCompletionCallsCount += 1

  startEngineResultCompletionResponse?(result, completion)
}
}

Motivation

This is an alternative solution for Sourcery AutoMockable. I wanted to create mock classes in different projects, as our product is built using tuist. I ran into the problem that Sourcery could only generate files in one folder, which was unacceptable to me. Therefore, I had to turn to the new features of Swift and study Macros.

Alternative