0

我有以下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 可能会引发异常。

4

2 回答 2

0

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

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

  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);

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

于 2019-03-12T11:13:04.230 回答
0

您正在模拟方法 +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 你的方法'正在尝试测试。

于 2019-01-16T16:03:09.200 回答