1

我正在测试的课程中有两种方法:

- (NSUInteger)sendBuffer:(uint8_t *)buffer length:(NSUInteger)length;
- (BOOL)sendFormattedCommandForAddress:(uint8_t)address 
                              withData:(uint8_t)data 
                        andCommandType:(ZKZSensorCommandType)commandType;

-sendFormattedCommandForAddress:withData:andCommandType:构建一个char数组并将指向该数组的指针传递给-sendBuffer:length:. 此数组的内容因addressdata和而异commandType。在我的测试中,我想验证是否构建了正确的数组并将其传递给-sendBuffer:length:. OCMock 不会让我对这个uint8_t *论点设定期望。OCMockito/OCHamcrest 不会让我使用部分模拟(还)。我尝试-sendBuffer:length:使用在我的测试用例类中调用方法的方法来调配该方法,并对该方法调用设置期望。但是,当调用 swizzled 方法时,self指向被测类而不是我的测试用例。我可以在我的测试类中保留缓冲区,然后在我的测试中检查这个缓冲区的内容,但我讨厌在生产代码中添加一些东西来支持测试。有没有人对如何测试这种行为有更好的建议?

4

2 回答 2

0

你不需要一个模拟框架来制作模拟。我认为挑战在于你实际上不想打电话-sendBuffer:length:在这种情况下,只需使用 Michael Feathers 的《有效使用遗留代码》一书中描述的子类和覆盖方法。

不知道您的班级名称,我将其称为发件人。这就是我要写的,直接放入 SenderTest.m:

@interface TestingSender : Sender
@property (assign, nonatomic) NSUInteger sendBufferCount;
@property (assign, nonatomic) uint8_t *sendBufferBuffer;
@property (assign, nonatomic) NSUInteger sendBufferLength;
@end

@implementation TestingSender

- (NSUInteger)sendBuffer:(uint8_t *)buffer length:(NSUInteger)length
{
    ++_sendBufferCount;
    _sendBufferBuffer = buffer;
    _sendBufferLength = length;
}

@end

然后测试代码创建一个 TestingSender 而不是一个 Sender。

于 2013-01-26T06:03:07.973 回答
0

虽然这可以说是一个见仁见智的问题,但综合单元测试的好处使得代码复杂性的小幅且包含的增量成为值得的权衡。在您描述的情况下,我认为您向生产类添加缓冲区以便可以在单元测试中检索和断言发送的最后一个字节序列的想法是一种非常好的方法。

我个人可能会添加一个布尔属性来控制是否维护缓冲区,只是为了避免在生产代码中最终发送大消息时任何意外的不必要的内存开销。单元测试设置当然会设置此属性,而应用程序/框架生产代码则不会。同样,关键是使添加的代码如此简单,以至于它显然是正确的。:-)

如果您希望或需要对生产类公开的接口严格严格,您还可以考虑使缓冲区维护代码依赖于条件编译。我个人更喜欢前一种方法,但每个人都有自己的方法。

于 2013-01-21T20:01:21.793 回答