【问题标题】:OCMock class category not working as expectedOCMock 类类别未按预期工作
【发布时间】:2019-01-15 11:27:08
【问题描述】:

我有以下UIImage 类别:

@implementation UIImage (Exception)

+ (nullable UIImage *)imageCanThrowWithData:(NSData *)data error:(NSError **)errorPtr
{
    UIImage *image = nil;

    @try {
        image = [self imageWithData:data];
    } @catch (id exception) {
        *errorPtr = [NSError errorWithDomain:@"mydomain" code:0 userInfo:nil];
    }

    return image;
}

@end

然后我尝试使用 OCMock 进行测试:

设置摘录 ...

beforeEach(^{
        NSString* labelPath = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"jpg"];
        imageData = [NSData dataWithContentsOfFile:labelPath];
        image = [UIImage imageWithData:imageData];
    });


it(@"should return the image if no exception is thrown", ^{
        id mock = OCMStrictClassMock([UIImage class]);

        NSError *error = nil;

        OCMStub([mock imageWithData:OCMOCK_ANY]).andReturn(image);

        OCMStub([mock imageMightThrowWithData:imageData error:&error]).andReturn([UIImage imageMightThrowWithData:imageData error:&error]);

        UIImage* resultImage = [[mock expect] imageMightThrowWithData:imageData error:&error];
        expect(resultImage).toNot(beNil());
        expect(error).to(beNil());

        [mock stopMocking];
    });

为什么resultImagenil。 备注:
我不是 OCMock 方面的专家,所以我可能会做一些幼稚的事情。
如果您正在处理核心数据外部存储,UIImage imageWithData 可能会引发异常。

【问题讨论】:

    标签: ios objective-c ocmock quick-nimble


    【解决方案1】:

    您正在模拟方法 +imageMightThrowWithData:error:,但随后尝试调用模拟方法作为模拟实现的一部分。我不确定结果会是什么,但如果只是失败并返回 nil,我不会感到惊讶。您正在使用 OCMStrictClassMock,这意味着您不能再调用 UIImage 上的任何类方法,包括您自己的。

    但是,由于 imageData 已经作为参数提供,因此您根本不需要模拟它 - 只需传递您要测试的参数即可。实际上,您也不需要模拟 +imageWithData: 。只需传递您似乎已经拥有的 imageData。我可能会看到 mocking +imageWithData: to throw with an non-strict mock,为了测试这种情况(如果你不能轻易得到一个 NSData 这将导致 Apple 方法首先抛出),但是对于这个测试我认为根本不需要使用 OCMock。所以只需删除 OCMStrictClassMock 和两个 OCMStub 调用,我认为它应该可以工作。

    如果你想模拟 imageWithData: 方法以便它更快返回,我想应该可以,但是使用 OCMClassMock 而不是严格的,这样你仍然可以测试你自己的类方法,然后不要 OCMStub您尝试测试的方法。

    【讨论】:

      【解决方案2】:

      您通常不会为您尝试测试的方法创建存根或期望。

      如果我正确理解了您的单元测试的目的,即在没有异常的情况下检查返回值是否不为零,您可以按照以下步骤操作:

      1. 存根+[UIImage imageWithData:] 以返回UIImage 对象。
      2. 调用+[UIImage imageCanThrowWithData: error:]并将返回值保存在局部变量中。
      3. 检查返回值是否不为零。
      id imageMock = OCMClassMock([UIImage class]);
      OCMStub([imageMock imageWithData:OCMOCK_ANY]).andReturn(imageMock);
      NSData *data = OCMClassMock([NSData class]);
      UIImage *result = [UIImage imageCanThrowWithData:data error:nil];
      XCTAssertNotNil(result);
      

      注意:最好每个测试只有一个断言,所以我建议创建一个单独的断言来检查在没有抛出异常时错误是否为零。

      【讨论】:

        猜你喜欢
        • 2013-12-01
        • 2021-10-13
        • 2019-02-18
        • 1970-01-01
        • 1970-01-01
        • 2017-01-01
        • 2013-03-10
        • 2017-02-26
        • 1970-01-01
        相关资源
        最近更新 更多