Xcode 15 beta 8: try await .purchase() consistently throws StoreKitError.Unknown during XCTest on iOS 17 simulator

In my Xcode 15 beta 8 setup, I'm encountering an issue with the iOS 17 simulator where StoreKit.Product.purchase() consistently throws StoreKit Error.Unknown while running XCTest.

  • Inside XCTest, I have declared SKTestSession(configuration: "").
  • I'm using try await StoreKit.Product.purchase(options: []).
  • However, it always throws StoreKit Error.Unknown. There's no such problem with the iOS 16.4 simulator, where I can retrieve the result and handle it appropriately. This issue is only present in the iOS 17 simulator.
  • Is there any necessary workaround or fix for this?
  • I've also included the console log output for your reference:
デフォルト	10:06:45.981812+0900	storekitd	AMSURLRequest: [597e_SK2] Failed to fetch client ID domains from bag. Defaulting to not including analytics cookies. error = { Error domain=AMSErrorDomain, code=204 | URL = http://localhost:XXXXX/inApps/history?REDACTED

The issue mentioned above persists even after updating to Xcode Version 15.0 (15A240d).

Same here. Any solutions?

I'm having the same problem. Is there any solution?

Have you tried adding session.resetToDefaultState() to the setupError?

    override func setUpWithError() throws {
        session = try SKTestSession(configurationFileNamed: "Configuration")
        session.resetToDefaultState()
        session.clearTransactions()
        session.disableDialogs = true 
    }

However, in some cases (like mine), you may need to add this line for each test block.

I don't know if this issue is caused by my logic or a bug in StoreKitTest.

    override func setUpWithError() throws {
        session = try SKTestSession(configurationFileNamed: "Configuration")
        // Even if I add this in setUpWithError, a test will always return an unexpected error.
        session.resetToDefaultState()
        session.clearTransactions()
        session.disableDialogs = true 
    }

    func testExample() async throws {
        // you'd need to insert this here but it depends on your code
        session.resetToDefaultState()
        session.clearTransactions()
        session.disableDialogs = true
        
        let products = try await Product.products(for: [productID])
        let value = try await products[0].purchase()
        switch value {
        case .success(let verificationResult):
            switch verificationResult {
            case .verified(let signedType):
                XCTAssertEqual(signedType.productID, productID)
                
            case .unverified:
                XCTFail()
            }

        case .userCancelled, .pending:
            XCTFail()
        @unknown default:
            XCTFail()
        }
    }

The WWDC2023 session mentioned using setSimulatedError(nil) to disable the previous setting, but currently, only setting nil didn't work, as far as I know.

Refer to: WWDC2023 Session

Additionally, once you set an error with setSimulatedError, a unit test always returns the error that you set previously (Configuration, as SKSession is shared).

I have (possibly) good news.

SKTestSession.failTransactionsEnabled has been depreacted since iOS17, but it behaves strangely on iOS17.

(lldb) po session.failTransactionsEnabled
false
(lldb) po session.failTransactionsEnabled = false
0 elements
(lldb) po session.failTransactionsEnabled
true

We may work around this issue by not setting a value for this variable.

// before
session.failTransactionsEnabled = false
// after
if #unavailable(iOS 17.0) {
    session.failTransactionsEnabled = false
}

In iOS17 we probably need to use simulatedError(forAPI:).

Any progress here? Still not working as of Xcode 15.2. The 16.4 simulator isn't working for me either. I'm getting:

Error enumerating unfinished transactions: Error Domain=ASDErrorDomain Code=500 "(null)" UserInfo={NSUnderlyingError=0x600000c5b780 {Error Domain=AMSErrorDomain Code=301 "Invalid Status Code" UserInfo={NSLocalizedDescription=Invalid Status Code, AMSURL=http://localhost:50398/inApps/history?REDACTED, AMSStatusCode=400, NSLocalizedFailureReason=The response has an invalid status code}}, storefront-country-code=USA, client-environment-type=XcodeTest(file:///Users/usrname/Library/Developer/XCTestDevices/AACF3F51-FA80-45B6-B9F1-A47574CE548F/data/Containers/Shared/AppGroup/749C8FFE-AF64-4A2D-A041-E19F365027A2/Documents/Persistence/Octane/com.apple.dt.xctest.tool/)}
 Missing transaction data for purchase
 Purchase did not return a transaction: unknown

If I set the simulated error to nil it's not working either. If I use let p = try await session.buyProduct(identifier: products.first!.id) I'm getting:

Failed to complete off-device buy for appstore.xyz. The purchase was successul, but it didn't return the expected transaction JWS.
error Error Domain=SKErrorDomain Code=0 "(null)"

Edit: Looks like it requires a host app. Then it works

Xcode 15 beta 8: try await .purchase() consistently throws StoreKitError.Unknown during XCTest on iOS 17 simulator
 
 
Q