Changing the internal properties of NSObjects (in particular, SKPaymentTransaction)

I'm trying to unit test our check validation server, and although I can change the internal API to avoid this problem, it means that we are not fully testing the client API, so I would like to avoid it.

As part of our API, we go through SKPaymentTransaction and then pass Transaction.transactionReceipt to our server.

To verify this correctly, I would like to create an instance of SKPaymentTransaction using the transactionReceipt method of my choice (valid and invalid values).

Unfortunately, SKPaymentTransaction defines the transactionReceipt property as read-only, and I cannot declare an extension / subclass that defines it as readwrite because of this .

I also don't seem to be able to use the SKPaymentTransaction pointer for char * to manually enter values ​​in memory, since Xcode will not allow this under ARC.

Does anyone have any idea how I can achieve what I'm looking for?

Thanks Lee

+4
source share
2 answers

It turns out that I can swap the recipient of the transaction Recipt to enter my own data into the call.

So, I get something like

-(void)test_function
{
    SKPaymentTransaction* invalidTransaction = [[SKPaymentTransaction alloc] init];

    Method swizzledMethod = class_getInstanceMethod([self class], @selector(replaced_getTransactionReceipt));
    Method originalMethod = class_getInstanceMethod([invalidTransaction class], @selector(transactionReceipt));

    method_exchangeImplementations(originalMethod, swizzledMethod);

    // Call to receipt verification server
}

- (NSData*)replaced_getTransactionReceipt
{
    return [@"blah" dataUsingEncoding:NSUTF8StringEncoding];
}

I wrote a blog post showing my process and talked a bit more here. http://engineering-game-dev.com/2014/07/23/injecting-data-into-obj-c-readonly-properties/

+3
source

SKPaymentTransaction (, MutableSKPaymentTransaction), readonly. SKPaymentTransaction, , SKPayment .

:

(MutableSKPaymentTransaction.h)

#import <StoreKit/StoreKit.h>

@interface MutableSKPaymentTransaction : SKPaymentTransaction

@property (readwrite, copy, nonatomic) NSError * error;
@property (readwrite, copy, nonatomic) SKPayment * payment;
@property (readwrite, copy, nonatomic) NSString * transactionIdentifier;
@property (readwrite, copy, nonatomic) NSDate * transactionDate;
@property (readwrite, copy, nonatomic) NSArray * downloads;
@property (readwrite, copy, nonatomic) SKPaymentTransaction *originalTransaction;
@property (assign, nonatomic) SKPaymentTransactionState transactionState;

@end

(MutableSKPaymentTransaction.m):

#import "MutableSKPaymentTransaction.h"

@implementation MutableSKPaymentTransaction

// readonly override
@synthesize error = _error;
@synthesize payment = _payment;
@synthesize transactionIdentifier = _transactionIdentifier;
@synthesize transactionDate = _transactionDate;
@synthesize downloads = _downloads;
@synthesize originalTransaction = _originalTransaction;
@synthesize transactionState = _transactionState;

@end
0

Source: https://habr.com/ru/post/1548326/


All Articles