Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate Mocks for Each Protocol Using Sourcery #1334

Open
sassiwalid opened this issue May 18, 2024 · 0 comments
Open

Generate Mocks for Each Protocol Using Sourcery #1334

sassiwalid opened this issue May 18, 2024 · 0 comments

Comments

@sassiwalid
Copy link

sassiwalid commented May 18, 2024

I am currently working on a project where I need to generate mocks for each protocol using Sourcery. To achieve this, I have written the following code in Stencil:
Stencil file code

`{% for type in types.all|protocol %}
// sourcery:file:Mock+{{ type.name }}.generated.swift
// swiftlint:disable line_length
// swiftlint:disable variable_name

import Foundation
#if os(iOS) || os(tvOS) || os(watchOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif

{% for import in argument.autoMockableImports %}
import {{ import }}
{% endfor %}

{% for import in argument.autoMockableTestableImports %}
@testable import {{ import }}
{% endfor %}

{% macro cleanString string %}{{ string | replace:"(","_" | replace:")","" | replace:":","_" | replace:"`","" | replace:" ","_" | replace:"?","_" | replace:"!","_" | replace:",","_" | replace:"->","_" | replace:"@","_" | replace:".","_" | replace:"[","" | replace:"]","" | replace:"<","" | replace:">","" | replace:"&","" | snakeToCamelCase }}{% endmacro %}
{%- macro swiftifyMethodName method -%}
    {%- set cleanMethodName %}{% call cleanString method.name %}{% endset %}
    {%- set cleanMethodReturnTypeName %}{% call cleanString method.actualReturnTypeName.name %}{% endset -%}
    {{ cleanMethodName | lowerFirstLetter }}{{ cleanMethodReturnTypeName | upperFirstLetter }}
{%- endmacro -%}

{% macro accessLevel level %}{% if level != 'internal' %}{{ level }} {% endif %}{% endmacro %}

{% macro staticSpecifier method %}{% if method.isStatic and not method.isInitializer %}static {% endif %}{% endmacro %}

{% macro methodThrowableErrorDeclaration method %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}ThrowableError: (any Error)?
{% endmacro %}

{% macro methodThrowableErrorUsage method %}
        if let error = {% call swiftifyMethodName method %}ThrowableError {
            throw error
        }
{% endmacro %}

{% macro methodReceivedParameters method %}
    {% set hasNonEscapingClosures %}
        {%- for param in method.parameters where param.isClosure and not param.typeAttributes.escaping %}
            {{ true }}
        {% endfor -%}
    {% endset %}
    {% if method.parameters.count == 1 and not hasNonEscapingClosures %}
        {% call swiftifyMethodName method %}Received{% for param in method.parameters %}{{ param.name|upperFirstLetter }} = {% if not param.name == "" %}{{ param.name }}{% else %}arg{{ param.index }}{% endif %}{% endfor %}
        {% call swiftifyMethodName method %}ReceivedInvocations.append({% for param in method.parameters %}{% if not param.name == "" %}{{ param.name }}{% else %}arg{{ param.index }}{% endif %}){% endfor %}
    {% else %}
    {% if not method.parameters.count == 0 and not hasNonEscapingClosures %}
        {% call swiftifyMethodName method %}ReceivedArguments = ({% for param in method.parameters %}{{ param.name }}: {{ param.name }}{% if not forloop.last%}, {% endif %}{% endfor %})
        {% call swiftifyMethodName method %}ReceivedInvocations.append(({% for param in method.parameters %}{{ param.name }}: {{ param.name }}{% if not forloop.last%}, {% endif %}{% endfor %}))
    {% endif %}
    {% endif %}
{% endmacro %}

{% macro methodClosureName method %}{% call swiftifyMethodName method %}Closure{% endmacro %}

{% macro closureReturnTypeName method %}{% if method.isOptionalReturnType %}{{ method.unwrappedReturnTypeName }}?{% else %}{{ method.returnTypeName }}{% endif %}{% endmacro %}

{% macro methodClosureDeclaration method %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call methodClosureName method %}: (({% for param in method.parameters %}{% call existentialClosureVariableTypeName param.typeName param.isVariadic true %}{% if not forloop.last %}, {% elif param.typeName.isClosure and param.typeName.closure.returnTypeName.name|contains:"any " %}{% endif %}{% endfor %}) {% if method.isAsync %}async {% endif %}{% if method.throws %}throws {% endif %}-> {% if method.isInitializer %}Void{% else %}{% call existentialVariableTypeName method.returnTypeName true %}{% endif %})?
{% endmacro %}

{% macro methodClosureCallParameters method %}{% for param in method.parameters %}{{ '&' if param.typeName.name | hasPrefix:"inout " }}{% if not param.name == "" %}{{ param.name }}{% else %}arg{{ param.index }}{% endif %}{% if not forloop.last %}, {% endif %}{% endfor %}{% endmacro %}

{% macro mockMethod method %}
    //MARK: - {{ method.shortName }}

    {% if method.throws %}
        {% call methodThrowableErrorDeclaration method %}
    {% endif %}
    {% if not method.isInitializer %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}CallsCount = 0
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}Called: Bool {
        return {% call swiftifyMethodName method %}CallsCount > 0
    }
    {% endif %}
    {% set hasNonEscapingClosures %}
        {%- for param in method.parameters where param.isClosure and not param.typeAttributes.escaping %}
            {{ true }}
        {% endfor -%}
    {% endset %}
    {% if method.parameters.count == 1 and not hasNonEscapingClosures %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}Received{% for param in method.parameters %}{{ param.name|upperFirstLetter }}: {{ '(' if param.isClosure }}({% call existentialClosureVariableTypeName param.typeName.unwrappedTypeName param.isVariadic false %}{{ ')' if param.isClosure }})?{% endfor %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}ReceivedInvocations{% for param in method.parameters %}: [{{ '(' if param.isClosure }}({% call existentialClosureVariableTypeName param.typeName.unwrappedTypeName param.isVariadic false %}){{ ')' if param.isClosure }}{%if param.typeName.isOptional%}?{%endif%}]{% endfor %} = []
    {% elif not method.parameters.count == 0 and not hasNonEscapingClosures %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}ReceivedArguments: ({% for param in method.parameters %}{{ param.name }}: {% if param.typeAttributes.escaping %}{% call existentialClosureTupleVariableTypeName param.typeName.unwrappedTypeName param.isVariadic false %}{% else %}{% call existentialClosureTupleVariableTypeName param.typeName param.isVariadic false %}{% endif %}{{ ', ' if not forloop.last }}{% endfor %})?
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}ReceivedInvocations: [({% for param in method.parameters %}{{ param.name }}: {% if param.typeAttributes.escaping %}{% call existentialClosureTupleVariableTypeName param.typeName.unwrappedTypeName param.isVariadic false %}{% else %}{% call existentialClosureTupleVariableTypeName param.typeName param.isVariadic false %}{% endif %}{{ ', ' if not forloop.last }}{% endfor %})] = []
    {% endif %}
    {% if not method.returnTypeName.isVoid and not method.isInitializer %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method %}ReturnValue: {{ '(' if method.returnTypeName.isClosure and not method.isOptionalReturnType or method.returnTypeName|contains:"any "}}{% call existentialVariableTypeName method.returnTypeName false %}{{ ')' if method.returnTypeName.isClosure and not method.isOptionalReturnType or method.returnTypeName|contains:"any " }}{{ '!' if not method.isOptionalReturnType }}
    {% endif %}
    {% call methodClosureDeclaration method %}

{% if method.isInitializer %}
    {% call accessLevel method.accessLevel %}required {{ method.name }} {
        {% call methodReceivedParameters method %}
        {% call methodClosureName method %}?({% call methodClosureCallParameters method %})
    }
{% else %}
    {% for name, attribute in method.attributes %}
    {% for value in attribute %}
    {{ value }}
    {% endfor %}
    {% endfor %}
    {% call accessLevel method.accessLevel %}{% call staticSpecifier method %}{% call methodName method %}{{ ' async' if method.isAsync }}{{ ' throws' if method.throws }}{% if not method.returnTypeName.isVoid %} -> {% call existentialVariableTypeName method.returnTypeName false %}{% endif %} {
        {% call swiftifyMethodName method %}CallsCount += 1
        {% call methodReceivedParameters method %}
        {% if method.throws %}
        {% call methodThrowableErrorUsage method %}
        {% endif %}
        {% if method.returnTypeName.isVoid %}
        {% if method.throws %}try {% endif %}{% if method.isAsync %}await {% endif %}{% call methodClosureName method %}?({% call methodClosureCallParameters method %})
        {% else %}
        if let {% call methodClosureName method %} = {% call methodClosureName method %} {
            return {{ 'try ' if method.throws }}{{ 'await ' if method.isAsync }}{% call methodClosureName method %}({% call methodClosureCallParameters method %})
        } else {
            return {% call swiftifyMethodName method %}ReturnValue
        }
        {% endif %}
    }

{% endif %}
{% endmacro %}

{% macro mockSubscript subscript index %}
    //MARK: - Subscript #{{ index }}
    {% call accessLevel subscript.readAccess %}subscript{% if subscript.isGeneric %}<{% for genericParameter in subscript.genericParameters %}{{ genericParameter.name }}{% if genericParameter.inheritedTypeName %}: {{ genericParameter.inheritedTypeName.name }}{% endif %}{{ ', ' if not forloop.last }}{% endfor %}>{% endif %}({% for parameter in subscript.parameters %}{{ parameter.asSource }}{{ ', ' if not forloop.last }}{% endfor %}) -> {{ subscript.returnTypeName.name }}{% if subscript.genericRequirements|count != 0 %} where {% for requirement in subscript.genericRequirements %}{{ requirement.leftType.name }} {{ requirement.relationshipSyntax }} {{ requirement.rightType.typeName.name }}{{ ', ' if not forloop.last }}{% endfor %}{% endif %} {
        {% if subscript.readAccess %}get{% if subscript.isAsync %} async{% endif %}{% if subscript.throws %} throws{% endif %} { fatalError("Subscripts are not fully supported yet") }{% endif %}
        {% if subscript.writeAccess %}set { fatalError("Subscripts are not fully supported yet") }{% endif %}
    }
{% endmacro %}

{% macro resetMethod method %}
        {# for type method which are mocked, a way to reset the invocation, argument, etc #}
        {% if method.isStatic and not method.isInitializer %} //MARK: - {{ method.shortName }}
        {% if not method.isInitializer %}
        {% call swiftifyMethodName method %}CallsCount = 0
        {% endif %}
        {% if method.parameters.count == 1 %}
        {% call swiftifyMethodName method %}Received{% for param in method.parameters %}{{ param.name|upperFirstLetter }}{% endfor %} = nil
        {% call swiftifyMethodName method %}ReceivedInvocations = []
        {% elif not method.parameters.count == 0 %}
        {% call swiftifyMethodName method %}ReceivedArguments = nil
        {% call swiftifyMethodName method %}ReceivedInvocations = []
        {% endif %}
        {% call methodClosureName method %} = nil
        {% if method.throws %}
        {% call swiftifyMethodName method %}ThrowableError = nil
        {% endif %}

        {% endif %}

{% endmacro %}

{% macro mockOptionalVariable variable %}
    {% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}: {% call existentialVariableTypeName variable.typeName false %}
{% endmacro %}

{% macro mockNonOptionalArrayOrDictionaryVariable variable %}
    {% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}: {% call existentialVariableTypeName variable.typeName false %} = {% if variable.isArray %}[]{% elif variable.isDictionary %}[:]{% endif %}
{% endmacro %}

{% macro mockNonOptionalVariable variable %}
    {% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}: {% call existentialVariableTypeName variable.typeName false %} {
        get { return {% call underlyingMockedVariableName variable %} }
        set(value) { {% call underlyingMockedVariableName variable %} = value }
    }
    {% set wrappedTypeName %}{% if variable.typeName.isProtocolComposition %}({% call existentialVariableTypeName variable.typeName false %}){% else %}{% call existentialVariableTypeName variable.typeName false %}{% endif %}{% endset %}
    {% call accessLevel variable.readAccess %}var {% call underlyingMockedVariableName variable %}: ({% call existentialVariableTypeName wrappedTypeName false %})!
{% endmacro %}

{% macro variableThrowableErrorDeclaration variable %}
    {% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}ThrowableError: Error?
{% endmacro %}

{% macro variableThrowableErrorUsage variable %}
            if let error = {% call mockedVariableName variable %}ThrowableError {
                throw error
            }
{% endmacro %}

{% macro variableClosureDeclaration variable %}
    {% call accessLevel variable.readAccess %}var {% call variableClosureName variable %}: (() {% if variable.isAsync %}async {% endif %}{% if variable.throws %}throws {% endif %}-> {% call existentialVariableTypeName variable.typeName true %})?
{% endmacro %}

{% macro variableClosureName variable %}{% call mockedVariableName variable %}Closure{% endmacro %}

{% macro mockAsyncOrThrowingVariable variable %}
    {% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}CallsCount = 0
    {% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}Called: Bool {
        return {% call mockedVariableName variable %}CallsCount > 0
    }

    {% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}: {% call existentialVariableTypeName variable.typeName false %} {
        get {% if variable.isAsync %}async {% endif %}{% if variable.throws %}throws {% endif %}{
            {% call mockedVariableName variable %}CallsCount += 1
            {% if variable.throws %}
            {% call variableThrowableErrorUsage variable %}
            {% endif %}
            if let {% call variableClosureName variable %} = {% call variableClosureName variable %} {
                return {{ 'try ' if variable.throws }}{{ 'await ' if variable.isAsync }}{% call variableClosureName variable %}()
            } else {
                return {% call underlyingMockedVariableName variable %}
            }
        }
    }
    {% call accessLevel variable.readAccess %}var {% call underlyingMockedVariableName variable %}: {% call existentialVariableTypeName variable.typeName false %}{{ '!' if not variable.isOptional }}
    {% if variable.throws %}
        {% call variableThrowableErrorDeclaration variable %}
    {% endif %}
    {% call variableClosureDeclaration method %}
{% endmacro %}

{% macro underlyingMockedVariableName variable %}underlying{{ variable.name|upperFirstLetter }}{% endmacro %}
{% macro mockedVariableName variable %}{{ variable.name }}{% endmacro %}
{# Swift does not support closures with implicitly unwrapped optional return value type. That is why existentialVariableTypeName.isNotAllowedToBeImplicitlyUnwrappedOptional should be true in such case #}
{% macro existentialVariableTypeName typeName isNotAllowedToBeImplicitlyUnwrappedOptional -%}
    {%- if typeName|contains:"<" and typeName|contains:">" -%}
        {{ typeName }}
    {%- elif typeName|contains:"any " and typeName|contains:"!"  -%}
        {{ typeName | replace:"any","(any" | replace:"!",")!" }}
    {%- elif typeName|contains:"any " and typeName.isOptional  -%}
        {{ typeName | replace:"any","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"any " and typeName.isClosure and typeName|contains:"?" -%}
        ({{ typeName | replace:"any","(any" | replace:"?",")?" }})
    {%- elif typeName|contains:"some " and typeName|contains:"!"  -%}
        {{ typeName | replace:"some","(some" | replace:"!",")!" }}
    {%- elif typeName|contains:"some " and typeName.isOptional  -%}
        {{ typeName | replace:"some","(some" | replace:"?",")?" }}
    {%- elif typeName|contains:"some " and typeName.isClosure and typeName|contains:"?" -%}
        ({{ typeName | replace:"some","(some" | replace:"?",")?" }})
    {%- elif typeName.isClosure -%}
        ({{ typeName }})
    {%- elif isNotAllowedToBeImplicitlyUnwrappedOptional -%}
        {{ typeName | replace:"!","" }}
    {%- else -%}
        {{ typeName }}
    {%- endif -%}
{%- endmacro %}
{# Swift does not support closures with variadic parameters of existential types as arguments. That is why existentialClosureVariableTypeName.isVariadic should be false when typeName is a closure #}
{% macro existentialClosureVariableTypeName typeName isVariadic keepInout -%}
    {% set name %}
        {%- if keepInout -%}
            {{ typeName }}
        {%- else -%}
            {{ typeName | replace:"inout ","" }}
        {%- endif -%}
    {% endset %}
    {%- if typeName|contains:"any " and typeName|contains:"!" -%}
        {{ name | replace:"any","(any" | replace:"!",")?" }}
    {%- elif typeName|contains:"any " and typeName.isOptional and typeName.isClosure -%}
        ({{ typeName.unwrappedTypeName| replace:"inout ","" | replace:"any","(any" | replace:"?",")?" }})?
    {%- elif typeName|contains:"any " and typeName.isClosure and typeName|contains:"?" and typeName.closure.parameters.count > 1 -%}
        {{ name | replace:"any","(any" | replace:"?",")?" | replace:") ->",")) ->" }}
    {%- elif typeName|contains:"any " and typeName.isClosure and typeName|contains:"?" and typeName.closure.parameters.count > 1 -%}
        {{ name | replace:"any","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"any " and typeName|contains:"?" -%}
        {{ name | replace:"any","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"some " and typeName|contains:"!" -%}
        {{ name | replace:"some","(any" | replace:"!",")?" }}
    {%- elif typeName|contains:"some " and typeName.isClosure and typeName|contains:"?" -%}
        {{ name | replace:"some","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"some " and typeName|contains:"?" -%}
        {{ name | replace:"some","(any" | replace:"?",")?" }}
    {%- elif isVariadic and typeName|contains:"any " -%}
        [({{ name }})]
    {%- elif isVariadic -%}
        {{ name }}...
    {%- else -%}
        {{ name|replace:"some ","any " }}
    {%- endif -%}
{%- endmacro %}
{# Swift does not support tuples with variadic parameters. That is why existentialClosureVariableTypeName.isVariadic should be false when typeName is a closure #}
{% macro existentialClosureTupleVariableTypeName typeName isVariadic keepInout -%}
    {% set name %}
        {%- if keepInout -%}
            {{ typeName }}
        {%- else -%}
            {{ typeName | replace:"inout ","" }}
        {%- endif -%}
    {% endset %}
    {%- if typeName|contains:"any " and typeName|contains:"!" -%}
        {{ name | replace:"any","(any" | replace:"!",")?" }}
    {%- elif typeName|contains:"any " and typeName.isOptional and typeName.isClosure -%}
        ({{ typeName.unwrappedTypeName| replace:"inout ","" | replace:"any","(any" | replace:"?",")?" }})?
    {%- elif typeName|contains:"any " and typeName.isClosure and typeName|contains:"?" -%}
        {{ name | replace:"any","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"any " and typeName|contains:"?" -%}
        {{ name | replace:"any","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"some " and typeName|contains:"!" -%}
        {{ name | replace:"some","(any" | replace:"!",")?" }}
    {%- elif typeName|contains:"some " and typeName.isClosure and typeName|contains:"?" -%}
        {{ name | replace:"some","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"some " and typeName|contains:"?" -%}
        {{ name | replace:"some","(any" | replace:"?",")?" }}
    {%- elif isVariadic -%}
        [{{ name }}]
    {%- else -%}
        {{ name|replace:"some ","any " }}
    {%- endif -%}
{%- endmacro %}
{% macro existentialParameterTypeName typeName isVariadic -%}
    {%- if typeName|contains:"any " and typeName|contains:"?," and typeName|contains:">?" -%}
        {{ typeName | replace:"any","(any" | replace:"?,",")?," }}
    {%- elif typeName|contains:"any " and typeName|contains:"!" -%}
        {{ typeName | replace:"any","(any" | replace:"!",")!" }}
    {%- elif typeName|contains:"any " and typeName.isOptional and typeName.isClosure -%}
        ({{ typeName.unwrappedTypeName | replace:"any","(any" | replace:"?",")?" }})?
    {%- elif typeName|contains:"any " and typeName.isClosure and typeName.closure.parameters.count > 1 and typeName.closure.returnTypeName.name|contains:"any " and typeName|contains:"?" -%}
        {{ typeName | replace:"any","(any" | replace:"?",")?" | replace:") ->",")) ->" }})
    {%- elif typeName|contains:"any " and typeName.isClosure and typeName.closure.returnTypeName.name|contains:"any " and typeName|contains:"?" -%}
        {{ typeName | replace:"any","(any" | replace:"?",")?" }})
    {%- elif typeName|contains:"any " and typeName.isClosure and typeName|contains:"?" -%}
        {{ typeName | replace:"any","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"any " and typeName.isOptional -%}
        {{ typeName | replace:"any","(any" | replace:"?",")?" }}
    {%- elif typeName|contains:"some " and typeName|contains:"!" -%}
        {{ typeName | replace:"some","(some" | replace:"!",")!" }}
    {%- elif typeName|contains:"some " and typeName.isClosure and typeName|contains:"?" -%}
        {{ typeName | replace:"some","(some" | replace:"?",")?" }}
    {%- elif typeName|contains:"some " and typeName.isOptional -%}
        {{ typeName | replace:"some","(some" | replace:"?",")?" }}
    {%- elif isVariadic -%}
        {{ typeName }}...
    {%- elif typeName.isClosure and typeName.closure.parameters.count > 0 and typeName.closure.parameters.last.isVariadic -%}
        {{ typeName }})
    {%- else -%}
        {{ typeName }}
    {%- endif -%}
{%- endmacro %}
{% macro methodName method %}func {{ method.shortName}}({%- for param in method.parameters %}{% if param.argumentLabel == nil %}_ {% if not param.name == "" %}{{ param.name }}{% else %}arg{{ param.index }}{% endif %}{%elif param.argumentLabel == param.name%}{{ param.name }}{%else%}{{ param.argumentLabel }} {{ param.name }}{% endif %}: {% if param.typeName.isClosure and param.typeName.closure.parameters.count > 1 %}({% endif %}{% call existentialParameterTypeName param.typeName param.isVariadic %}{% if not forloop.last %}, {% endif %}{% endfor -%}){% endmacro %}

{% for type in types.protocols where type.based.AutoMockable or type|annotated:"AutoMockable" %}{% if type.name != "AutoMockable" %}
{% call accessLevel type.accessLevel %}class {{ type.name }}Mock: {{ type.name }} {

    {% if type.accessLevel == "public" %}public init() {}{% endif %}

{% for variable in type.allVariables|!definedInExtension %}
    {% if variable.isAsync or variable.throws %}{% call mockAsyncOrThrowingVariable variable %}{% elif variable.isOptional %}{% call mockOptionalVariable variable %}{% elif variable.isArray or variable.isDictionary %}{% call mockNonOptionalArrayOrDictionaryVariable variable %}{% else %}{% call mockNonOptionalVariable variable %}{% endif %}
{% endfor %}

{% if type.allMethods|static|count != 0 and type.allMethods|initializer|count != type.allMethods|static|count %}
    static func reset()
    {
    {% for method in type.allMethods|static %}
        {% call resetMethod method %}
    {% endfor %}
    }
{% endif %}

{% for method in type.allMethods|!definedInExtension %}
    {% call mockMethod method %}
{% endfor %}

{% for subscript in type.allSubscripts|!definedInExtension %}
    {% call mockSubscript subscript forloop.counter %}
{% endfor %}
}
{% endif %}{% endfor %}
{% endfor %}`

However, I am encountering some issues and need assistance to resolve them. Here are the specific problems I am facing:
Instead of having a mock for each protocol type, I get a generated file with the same stencil code!
Capture d’écran 2024-05-18 à 14 38 24

Steps to Reproduce

I use fastLane to launch sourcery. In my fastfile I have a lane to call sourcery for doing the job

lane :generateMocks do
  sh("bundle exec mint run chamnan1111/SwiftyMocky@feature/support-sourcery-v2.0.3 generate")
end 

I call fastlane lane like this : bundle exec fastlane generateMocks
In my Mockfile I specify the path to my stencil file like this

sourceryCommand: mint run krzysztofzablocki/[email protected] sourcery
sourceryTemplate: ../Sourcery/mock.stencil

in my Mockfile, I specify also the output as a folder that will contains eventually mock files
output: ./AppTests/Mocks/Generated

Additional Information

  • Sourcery Version: 2.1.8

  • Operating System: macOS Sonoma 14.3.1

Request for Help

I would greatly appreciate any guidance or suggestions on how to resolve these issues. Thank you in advance for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant