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

Issues with SPM packages and Container static shared instance #179

Open
alaw-viator opened this issue Jan 23, 2024 · 2 comments
Open

Issues with SPM packages and Container static shared instance #179

alaw-viator opened this issue Jan 23, 2024 · 2 comments

Comments

@alaw-viator
Copy link

alaw-viator commented Jan 23, 2024

We've been using Factory for a while in our project trouble free. However, we've just begun to run into issues whereby all of our mocked dependencies setup from unit tests are being ignored.

This issue started when we made the final migration to remove CocoaPods in favour of SPM. Previously we were utilising development CocoaPods for all our modules, whereas these are now local SPM packages. A trimmed down example of one of our SPM module packages looks like this:

let package = Package(
    name: "ModuleA",
    defaultLocalization: "en",
    platforms: [
        .iOS(.v15),
    ],
    products: [
        .library(
            name: "ModuleA",
            targets: ["ModuleA"]
        ),
        .library(
            name: "ModuleAMocks",
            targets: ["ModuleAMocks"]
        ),
    ],
    dependencies: [
        .package(
            url: "https://github.com/hmlongco/Factory.git",
            exact: "2.2.0"
        )
    ],
    targets: [
        .target(
            name: "ModuleA",
            dependencies: [
                .product(name: "Factory", package: "Factory")
            ],
            path: "Framework/Sources",
            plugins: [
            ]
        ),
        .target(
            name: "ModuleAMocks",
            dependencies: [
                .byName(name: "ModuleA"),
            ],
            path: "Tests/Sources/Mocks",
            plugins: [
            ]
        ),
        .testTarget(
            name: "ModuleATests",
            dependencies: [
                .byName(name: "ModuleA"),
                .byName(name: "ModuleAMocks")
            ],
            path: "Tests/Sources",
            exclude: [
                "Mocks",
            ],
            plugins: [
            ]
        ),
    ]
)

And the DI container defined in the ModuleA target:

public final class ModuleAContainer: SharedContainer {
    public static var shared = ModuleAContainer()
    public var manager = ContainerManager()
}

And then a mock extension on the container defined in the ModuleAMocks target

public extension ModuleA {
    static func setUpMocks() {
      // shared.depdency.register { mockedDependency }
      // ...
    }

Each unit test class then calls the required ModuleA.setUpMocks() etc in the setup.

It's worth also mentioning that each modules suite of unit tests run fine when run in isolation, i.e. directly from the SPM package. However, the issues are back in the main project, both on the test plan comprising the suite of units tests which are part of the main projects test target and the test plan comprising of all of the SPM modules unit tests.

Despite the tests setting all the mocked dependencies, when the projects main code resolves those dependencies during a test execution, a new instance of the container is created, not the statically allocated one created by the test fixture calling setUpMocks().

Given that static variables are scoped to a module in Swift (by design) and SPM packages are compiled separately to one another, I'm struggling to see how it's possible to use Factory in the context of a modularised project which utilises SPM for those modules because having a statically allocated shared container is a fundamental requirement of a container.

Has anyone else encountered similar issues and if so how did you approach this problem? Thanks!

@kuchmiyalex
Copy link

I believe we're experience a similar outcome while using Factory as an SPM dependency across multiple modules.

While running unit tests in main project the container is being initialized more than once and instead of using mock it uses real implementation from the ModuleA.

I've created a demo project including two SPM modules(which runs fine in isolation), but then linked together into main target produce multiple container recreation.
If ModuleBMocks is removed from ProjectTests's linked frameworks then unit tests working properly in the main target(testBuilderExample).
Here are two projects, one containing ModuleBMocks dependency and another doesn't.
Please suggest any workaround here, thanks!

ProjectSuccess.zip

ProjectFail.zip

@emans
Copy link

emans commented Jan 30, 2024

I am also having a similar situation, could you please help with this?

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

3 participants