如何使用 OCMock 初始化带有存根值的对象

发布于 2024-12-04 15:15:48 字数 1415 浏览 0 评论 0原文

如何对 init 方法中使用的方法进行存根?

我的类中的相关方法:

- (id)init
{
    self = [super init];
    if (self) {
        if (self.adConfigurationType == AdConfigurationTypeDouble) {
             [self configureForDoubleConfiguration];
        }
        else {
            [self configureForSingleConfiguration];
        }
    }
    return self;
}

- (AdConfigurationType)adConfigurationType
{
    if (adConfigurationType == NSNotFound) {
        if ((random()%2)==1) {
            adConfigurationType = AdConfigurationTypeSingle;
        }
        else {
            adConfigurationType = AdConfigurationTypeDouble;
        }
    }
    return adConfigurationType;
}

我的测试:

- (void)testDoubleConfigurationLayout
{
    id mockController = [OCMockObject mockForClass:[AdViewController class]];
    AdConfigurationType type = AdConfigurationTypeDouble;
    [[[mockController stub] andReturnValue:OCMOCK_VALUE(type)] adConfigurationType];

    id controller = [mockController init];

    STAssertNotNil([controller smallAdRight], @"Expected a value here");
    STAssertNotNil([controller smallAdRight], @"Expected a value here");
    STAssertNil([controller largeAd], @"Expected nil here");
}

我的结果:

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'OCMockObject [AdViewController]:调用了意外的方法:smallAdRight'

那么我将如何访问OCMockObject中的AdViewController?

Ho do I stub a method used in the init method?

The related methods in my class:

- (id)init
{
    self = [super init];
    if (self) {
        if (self.adConfigurationType == AdConfigurationTypeDouble) {
             [self configureForDoubleConfiguration];
        }
        else {
            [self configureForSingleConfiguration];
        }
    }
    return self;
}

- (AdConfigurationType)adConfigurationType
{
    if (adConfigurationType == NSNotFound) {
        if ((random()%2)==1) {
            adConfigurationType = AdConfigurationTypeSingle;
        }
        else {
            adConfigurationType = AdConfigurationTypeDouble;
        }
    }
    return adConfigurationType;
}

My test:

- (void)testDoubleConfigurationLayout
{
    id mockController = [OCMockObject mockForClass:[AdViewController class]];
    AdConfigurationType type = AdConfigurationTypeDouble;
    [[[mockController stub] andReturnValue:OCMOCK_VALUE(type)] adConfigurationType];

    id controller = [mockController init];

    STAssertNotNil([controller smallAdRight], @"Expected a value here");
    STAssertNotNil([controller smallAdRight], @"Expected a value here");
    STAssertNil([controller largeAd], @"Expected nil here");
}

My result:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'OCMockObject[AdViewController]: unexpected method invoked: smallAdRight '

So how will I access the AdViewController in the OCMockObject?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江湖正好 2024-12-11 15:15:49

如果您使用 mockForClass: 方法,您将需要为模拟类中调用的每个方法提供存根实现。在您的第一次测试中包括使用 [controllersmallAdRight] 进行的调用。

相反,您可以使用 niceMockForClass: 方法,该方法将忽略任何未模拟的消息。

另一种替代方法是实例化您的 AdViewController,然后使用 partialMockForObject: 方法为其创建部分模拟。这样控制器类的内部将完成主要部分的工作。

只是,您是否正在尝试测试 AdViewController 或使用它的类?看来您正在尝试模拟整个班级,然后测试它是否仍然表现正常。如果您想测试 AdViewController 在注入某些值时是否按预期运行,那么您最好的选择很可能是 partialMockForObject: 方法:

- (void)testDoubleConfigurationLayout {     
  AdViewController *controller = [AdViewController alloc];
  id mock = [OCMockObject partialMockForObject:controller];
  AdConfigurationType type = AdConfigurationTypeDouble;
  [[[mock stub] andReturnValue:OCMOCK_VALUE(type)] adConfigurationType];

  // You'll want to call init after the object have been stubbed
  [controller init]

  STAssertNotNil([controller smallAdRight], @"Expected a value here");
  STAssertNotNil([controller smallAdRight], @"Expected a value here");
  STAssertNil([controller largeAd], @"Expected nil here");
}

If you use the mockForClass: method you will need to provided stubbed implementations for each and every method that are called in the mocked class. including your call into it with [controller smallAdRight] in your first test.

Instead you can use the niceMockForClass: method which will just ignore any messages which are not mocked.

Another alternative is to instantiate your AdViewController and then create a partial mock for it using the partialMockForObject: method. This way the internals of the controller class will do the main part of the work.

Just a though... are you trying to test the AdViewController or a class which uses it? It appears that you are trying to mock the entire class and then test if it still behaves normally. If you want to test that AdViewController behaves as expected when certain values are injected then your best option is most likely the partialMockForObject: method:

- (void)testDoubleConfigurationLayout {     
  AdViewController *controller = [AdViewController alloc];
  id mock = [OCMockObject partialMockForObject:controller];
  AdConfigurationType type = AdConfigurationTypeDouble;
  [[[mock stub] andReturnValue:OCMOCK_VALUE(type)] adConfigurationType];

  // You'll want to call init after the object have been stubbed
  [controller init]

  STAssertNotNil([controller smallAdRight], @"Expected a value here");
  STAssertNotNil([controller smallAdRight], @"Expected a value here");
  STAssertNil([controller largeAd], @"Expected nil here");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文