Objective c 什么';对于参数为';s不可变且没有初始值设定项?

Objective c 什么';对于参数为';s不可变且没有初始值设定项?,objective-c,unit-testing,Objective C,Unit Testing,问题 我试图对协议方法的实现进行单元测试,该方法将不在项目中的不可变对象作为参数。此对象未公开任何设置其属性的初始值设定项。在这种情况下,单元测试的最佳方式是什么 我尝试的 我尝试将属性子类化并强制转换为readwrite,但只有当它们显式标记为@protected时,您才能访问超类的ivar。由于该类不在我的项目中,因此我无法将新范围重新分配给ivar 我也不能模拟不存在的setter,并且ivar不能通过模拟对象直接写入 最后,我决定添加一个附加方法,该方法将调用该方法,只传递我可以设置其属

问题

我试图对协议方法的实现进行单元测试,该方法将不在项目中的不可变对象作为参数。此对象未公开任何设置其属性的初始值设定项。在这种情况下,单元测试的最佳方式是什么

我尝试的

我尝试将属性子类化并强制转换为readwrite,但只有当它们显式标记为@protected时,您才能访问超类的ivar。由于该类不在我的项目中,因此我无法将新范围重新分配给ivar

我也不能模拟不存在的setter,并且ivar不能通过模拟对象直接写入

最后,我决定添加一个附加方法,该方法将调用该方法,只传递我可以设置其属性的对象,并且我在单元测试中介绍了该附加方法

在这个场景中有更好的单元测试方法吗

我的场景的细节

我正在尝试对来自WebKit的WKScriptMessageHandler协议的的实现进行单元测试,但找不到传递WKScriptMessage或WKUserContentController实例的方法,且未设置任何属性

为了对其进行单元测试,我创建了一个新方法,该方法采用“id”类型的参数,并从userContentController:didReceiveScriptMessage:调用它,传递WKScriptMessage的属性。

这对您有帮助吗

TestMessage.h

#import <WebKit/WebKit.h>

@interface TestMessage : WKScriptMessage

- (id) initWithBody:(id)body
          frameInfo:(WKFrameInfo*)frameInfo
               name:(NSString*)name
            webView:(WKWebView*)webView;

@end
因此,您基本上是创建一个具有匹配属性的子类,然后覆盖超类属性的getter,以返回您完全可以访问的那些属性的值

这对我来说是一个简单的测试(我相信你的场景更复杂):

这对你有帮助吗

TestMessage.h

#import <WebKit/WebKit.h>

@interface TestMessage : WKScriptMessage

- (id) initWithBody:(id)body
          frameInfo:(WKFrameInfo*)frameInfo
               name:(NSString*)name
            webView:(WKWebView*)webView;

@end
因此,您基本上是创建一个具有匹配属性的子类,然后覆盖超类属性的getter,以返回您完全可以访问的那些属性的值

这对我来说是一个简单的测试(我相信你的场景更复杂):


是的!这正是我需要的。谢谢你的分享,真的!这正是我需要的。谢谢分享
- (void) testMessageHandler
{
    WKWebView* webView = [[WKWebView alloc] init];
    WKUserContentController* controller = [[WKUserContentController alloc] init];
    WKFrameInfo* info = [[WKFrameInfo alloc] init];
    NSDictionary* testBody = @{@"testKey" : @"testVal" };

    TestMessage* testMessage = [[TestMessage alloc] initWithBody:testBody
                                                       frameInfo:info
                                                            name:@"Message Name"
                                                         webView:webView];

    // some object conforming to the WKScriptMessageHandler protocol
    [self userContentController:controller
        didReceiveScriptMessage:testMessage];
}


- (void)userContentController:(nonnull WKUserContentController *)userContentController
      didReceiveScriptMessage:(nonnull WKScriptMessage *)message
{
    NSLog(@"Received Script Message... (%@)", message.body);
}