OCMock:使用调用的 NSDictionary 参数测试方法

OCMock: testing a method with an NSDictionary argument being invoked

我有以下 类:

@interface ReportsArchiver

-(void)fileReport:(NSDictionary*)reports;

@end

@interface OfficeManager

@property (nonatomic) ReportsArchiver* reportsArchiver;
-(void) reportIncident:(NSString*)name description:(NSString*)description;

@end

使用 OCMock 我想测试当调用 [officeManager reportIncident:@"fire alarm" description: @"false fire alarm"] 然后 [officeManager.reportsArchiver fileReport] 被字典 @{@"name": @"fire alarm", @"description": @"false fire alarm"}.

调用

到目前为止,我为此编写了以下代码:

OfficeManager* officeManager = [OfficeManager new];
id reportsArchiverMock = OCMClassMock([ReportsArchiver class]);
officeManager.reportsArchiver = reportsArchiverMock;
NSDictionary* expectedReportDictionary = @{@"name": @"fire alarm", @"description": @"false fire alarm"};

[officeManager reportIncident:@"fire alarm" description: @"false fire alarm"];

// This call will fail because it checks for object equality, not dictionary equality.    
OCMVerify([reportsArchiverMock fileReport:expectedReportDictionary]);

如何使用 OCMock 验证 [reportsArchiverMock fileReport:{(NSDictionary*)] 是通过相同的 NSDictionary 调用的?

从那时起,我在 Twitter 上收到了@wolffan 和@catehstn 的建议,以下是我找到的解决方案。

  1. 使用 OCMExpect - 与 OCMVerify 不同,OCMExpect 比较 NSDictionaries 正确。这是我找到的最干净的解决方案。

    OfficeManager* officeManager = [OfficeManager new];
    id reportsArchiverMock = OCMClassMock([ReportsArchiver class]);
    officeManager.reportsArchiver = reportsArchiverMock;
    NSDictionary* expectedReportDictionary = @{@"name": @"fire alarm", @"description": @"false fire alarm"};
    
    OCMExpect([reportsArchiverMock fileReport:expectedReportDictionary])
    [officeManager reportIncident:@"fire alarm" description: @"false fire alarm"];
    
    OCMVerifyAll(reportsArchiverMock);
    
  2. 使用 OCMStub 并检查回调中的参数。这是一个非常混乱的解决方案。

.

OfficeManager* officeManager = [OfficeManager new]
id reportsArchiverMock = OCMClassMock([ReportsArchiver class]);
officeManager.reportsArchiver = reportsArchiverMock;
NSDictionary* expectedReportDictionary = @{@"name": @"fire alarm", @"description": @"false fire alarm"};            

void (^reportIncidentInvocation)(NSInvocation *) = ^(NSInvocation *invocation) {
       __unsafe_unretained NSInvocationOperation *reportDictionary;
       [invocation getArgument: &reportDictionary atIndex: 2];
       XCTAssertTrue([expectedPropertiesCollection isEqualToDictionary:(NSDictionary*)reportDictionary]);
    };
OCMStub([officeManager reportIncident:[OCMArg any]]).andDo(reportIncidentInvocation);

OCMVerify([reportsArchiverMock fileReport:expectedReportDictionary]);