apollographql / apollo-ios

📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.
https://www.apollographql.com/docs/ios/
MIT License
3.87k stars 717 forks source link

Adding in mocks is causing our tests to fail. #3397

Closed squarefrog closed 3 months ago

squarefrog commented 3 months ago

Summary

We've successfully been using apollo-ios for a while now, albeit with json fixtures. One of my team did some work to try and implement mocks by creating a new package with the mocks inside.

This all worked well until we add that package to our test target. Even without using the mocks, some of our tests have begun failing. All of these tests are testing that our stubbed API client handles specific Apollo errors. If we remove the mocks package, then the tests run successfully again.

When the mocks package is included, I noticed we get a slew of errors in the console stating that a class is implemented in two targets. Here's one example:

objc[30014]: Class _TtC6Apollo16URLSessionClient is implemented in both /Users/name/Library/Developer/Xcode/DerivedData/ProjectName-fbxvsflrsknlegeyngegyzacipox/Build/Products/Debug-iphonesimulator/PackageFrameworks/Apollo_171E9C48F1D7AD_PackageProduct.framework/Apollo_171E9C48F1D7AD_PackageProduct (0x10b24af38) and /Users/name/Library/Developer/XCTestDevices/9D100240-3718-474B-9094-9FAD4F3862C7/data/Containers/Bundle/Application/88AE36A9-FFE0-4669-B2B2-F8CCF6766A48/ProjectName.app/PlugIns/ProjectNameTests.xctest/ProjectNameTests (0x112e30d70). One of the two will be used. Which one is undefined.

We explicitly link the Mocks package to our test target, which seems to be implicitly containing a copy of the Apollo library, causing the duplication error.

We have a separate package for our GraphQL targets, and this is the only package that directly depends on the Apollo package.

Package.swift ```swift // swift-tools-version: 5.8 // swiftlint:ignore:previous file_header // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "GraphQL", platforms: [ .iOS(.v16), .macOS(.v13) // Required to allow the `apollo-ios-cli` to install from Fastlane. ], products: [ .library(name: "AccountsAPI", targets: ["AccountsAPI"]), .library(name: "API", targets: ["API"]), .library(name: "MockAPI", targets: ["MockAPI"]), .library(name: "OffersAPI", targets: ["OffersAPI"]), .library(name: "OffersAPIMocks", targets: ["OffersAPIMocks"]), ], dependencies: [ .package( url: "https://github.com/apollographql/apollo-ios.git", exact: "1.12.2" ), ], targets: [ .target( name: "AccountsAPI", dependencies: [ .product(name: "Apollo", package: "apollo-ios"), .product(name: "ApolloAPI", package: "apollo-ios") ], exclude: [ "Templates", "accounts-config.json" ] ), .target( name: "API", dependencies: [ .product(name: "Apollo", package: "apollo-ios"), .product(name: "ApolloAPI", package: "apollo-ios") ] ), .target( name: "MockAPI", dependencies: [ "API", .product(name: "Apollo", package: "apollo-ios"), .product(name: "ApolloAPI", package: "apollo-ios") ] ), .target( name: "OffersAPI", dependencies: [ .product(name: "Apollo", package: "apollo-ios"), .product(name: "ApolloAPI", package: "apollo-ios") ], exclude: [ "Templates", "offers-config.json" ] ), .target( name: "OffersAPIMocks", dependencies: [ "OffersAPI", .product(name: "ApolloTestSupport", package: "apollo-ios"), ] ), .testTarget(name: "APITests", dependencies: [ "API", "OffersAPI", ]) ] ) ```
Offers configuration json ```json { "schemaNamespace" : "OffersAPI", "input" : { "operationSearchPaths" : [ "./Templates/**/*.graphql" ], "schemaSearchPaths" : [ "./Templates/Schema/Offers.graphqls" ] }, "output" : { "testMocks" : { "absolute" : { "path" : "../OffersAPIMocks" } }, "schemaTypes" : { "path" : ".", "moduleType" : { "other" : { } } }, "operations" : { "inSchemaModule" : { } } }, "schemaDownloadConfiguration": { "downloadMethod": { "introspection": { "endpointURL": "https://graphql.staging.ourdomain.com/graphql/v1/query", "httpMethod": { "POST": {} }, "includeDeprecatedInputValues": false, "outputFormat": "SDL" } }, "downloadTimeout": 60, "headers": [], "outputPath": "./Templates/Schema/Offers.graphqls" }, "options": { "selectionSetInitializers" : { "namedFragments" : true } } } ```

Version

1.12.2

Steps to reproduce the behavior

We will try to produce an example project exhibiting the issue and attach here.

Logs

No response

Anything else?

No response

AnthonyMDev commented 3 months ago

Thank you for the report. We've been tracking related issues in #2686 and people have found workarounds by explicitly linking in the past, but it sounds like that's not working for you.

We're looking into using the new mergable libraries feature of Swift to see if that helps us resolve this.

I'm going to close this as a duplicate of that issue. Follow along there for updates, and please feel free to reply if you figure out any workaround!

github-actions[bot] commented 3 months ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better.

squarefrog commented 3 months ago

Thanks we’ll have a look through the other thread this week.

We’ve been trying to modify your example project to reproduce the issue, but to no avail. Right now I suspect it could be an intricacy of our project.

We will keep trying though, thanks for the reply!