How I can mock an SKProduct, SKProductDiscount, SKProductSubscriptionPeriod and other classes realted to StoreKit in Swift?

The solution is to extend the SKProduct class and set the fields which you need to:

import StoreKit

public extension SKProduct {

    convenience init(
        identifier: String,
        price: NSDecimalNumber,
        priceLocale: Locale) {
        self.init()
        self.setValue(identifier, forKey: "productIdentifier")
        self.setValue(price, forKey: "price")
        self.setValue(priceLocale, forKey: "priceLocale")
    }
}

The same with SKProductDiscount class:

import StoreKit

public extension SKProductDiscount {

    convenience init(
        price: String,
        priceLocale: Locale,
        subscriptionPeriod: SKProductSubscriptionPeriod,
        numberOfPeriods: Int) {
        self.init()
        self.setValue(NSDecimalNumber(string: price), forKey: "price")
        self.setValue(priceLocale, forKey: "priceLocale")
        self.setValue(subscriptionPeriod, forKey: "subscriptionPeriod")
        self.setValue(numberOfPeriods, forKey: "numberOfPeriods")
    }
}

And SKProductSubscriptionPeriod extension:

public extension SKProductSubscriptionPeriod {

    convenience init(
        numberOfUnits: Int,
        unit: SKProduct.PeriodUnit) {
        self.init()
        self.setValue(numberOfUnits, forKey: "numberOfUnits")
        self.setValue(unit.rawValue, forKey: "unit")
    }
}

In the above extension, there is a tricky part for the key “unit”. We don’t set the value as unit but we are passing a raw value of it. I was struggling with this and this post helped me.