代码之家  ›  专栏  ›  技术社区  ›  pgb

OCUnit测试通知传递

  •  12
  • pgb  · 技术社区  · 17 年前

    我正在使用OCUnit对模型进行单元测试,并希望断言预期的通知已发布。为此,我做了如下工作:

    - (void)testSomething {
        [[NSNotificationCenter defaultCenter] addObserver:notifications selector:@selector(addObject:) name:kNotificationMoved object:board];
    
        Board *board = [[Board alloc] init];
        Tile *tile = [Tile newTile];
    
        [board addTile:tile];
    
        [board move:tile];
    
        STAssertEquals((NSUInteger)1, [notifications count], nil);
        // Assert the contents of the userInfo as well here
    
        [board release];
    }
    

    这个想法是 NSNotificationCenter NSMutableArray 称其为 addObject: 方法

    然而,当我运行它时,我看到 添加对象: 可变数组 )导致OCUnit停止工作。但是,如果我注释掉一些代码(例如 release 调用或添加新的单元测试)一切按预期开始工作。

    我想这一定是因为时间问题,或者 通知中间 以某种方式依赖于运行循环。

    Board 给我自己注射 通知中间 ,但我正在寻找一种更快的方法(也许是一些如何替换 通知中间 动态地)。

    3 回复  |  直到 17 年前
        1
  •  5
  •   pgb    17 年前

    发现了问题。在测试通知时,需要在测试完观察器后将其删除。工作代码:

    - (void)testSomething {
        [[NSNotificationCenter defaultCenter] addObserver:notifications selector:@selector(addObject:) name:kNotificationMoved object:board];
    
        Board *board = [[Board alloc] init];
        Tile *tile = [Tile newTile];
    
        [board addTile:tile];
    
        [board move:tile];
    
        STAssertEquals((NSUInteger)1, [notifications count], nil);
        // Assert the contents of the userInfo as well here
    
        [board release];
        [[NSNotificationCenter defaultCenter] removeObserver:notifications name:kNotificationMoved object:board];
    }
    

    如果在测试运行并释放某些局部变量后,无法删除观察者,则在运行触发相同通知的任何后续测试时,通知中心将尝试通知这些旧对象。

        2
  •  0
  •   Nikolai Ruhe    17 年前

    我认为你发布的片段中的所有内容都是正确的。可能可变数组“通知”有问题。您是否初始化并正确保留了它?尝试手动添加一些对象,而不是使用通知技巧。

        3
  •  0
  •   TimM    17 年前

    如果您怀疑您的测试有定时问题,您可能需要考虑将您自己的通知机制注入到您的板对象(这可能只是现有苹果版本的包装)。

    即:

    Board *board = [[Board alloc] initWithNotifier: someOtherNotifierConformingToAProtocol];
    

    假设您的board对象发布了一些通知-您可以在代码中使用注入的通知程序:

    -(void) someBoardMethod {
    
      // ....
    
      // Send your notification indirectly through your object
      [myNotifier pushUpdateNotification: myAttribute];
    }
    

    在您的测试中—您现在有了一个可用于测试的间接级别,因此您可以实现一个符合您的协议的测试类—并且可能会计算pushUpdateNotification:调用的次数。在实际代码中,您封装了可能已经存在于执行通知的板中的代码。

    当然,这是一个典型的例子,说明了MockObjects在哪里是有用的——还有一个OCMock,它可以让您在不必使用测试类进行计数的情况下实现这一点(请参见: http://www.mulle-kybernetik.com/software/OCMock/ )

    [[myMockNotifer expect] pushUpdateNotification: someAttribute]; 
    

    或者,您可以考虑使用委托而不是通知。这里有一组很好的赞成/反对幻灯片: http://www.slideshare.net/360conferences/nsnotificationcenter-vs-appdelegate .