规则是这样说的
Only mock objects that you own.
我想我理解这样做的原因 - 框架提供的模拟类可能会导致奇怪的行为。
还有什么选择?
当您需要使用 NSDate 的虚拟日期时怎么办?
在过去,我将日期方法从 NSDate 调换到我自己的类 - NSDateMock - 但有些东西告诉我那真的是错误的!
一个解决方案 - 一个包装器?
创建一个 NSDate 的包装器,但是你必须实现它的所有方法。
或者您会只实现您正在使用的那些吗?这似乎是一种困惑的方式。
我的问题
模拟不属于您的类(例如 NSDate)的好方法是什么?
更新 1
我找到了 this article on mocking这似乎暗示写一个薄包装是要走的路。我不太清楚为什么,但我觉得这是一个 hack。话又说回来,它可以使代码更具表现力。
但这提出了一个问题,在 NSDate 的情况下,您是否将包装类注入(inject)到需要知道日期的每个类中?!当然不是...
更新 2
关于这个问题已经有一些很好的答案,但我仍在等待其他答案 - 一定有一个确定的方法,对吗?我仍然不明白类别如何给我一个我可以控制的虚拟对象。
最佳答案
一般来说,这是一个“如何模拟静态/类级方法”的问题,谷歌搜索显示了很多不同的想法,所以主要归结为品味。
我认为部分模拟是一种代码味道,因为它表明您的被测类 (CUT) 不可测试 -> 是时候重构了。
我过去用两种方式解决这个问题:
1.) 将 DateProvider(它是一个接口(interface))传递到 CUT 的构造函数中
interface DateProvider
date timenow()
end
在测试时,这是您的 MockDateProvider,您可以从测试类更改状态。我可能会使用可以在测试中更改的公共(public)静态字段
class MockDateProvider :: DateProvider
public static field fakeDate
date timenow ()
return fakedate
end
end
在实际系统中,它只有您使用的日期创建方法。
class RealDateProvider :: DateProvider
date timenow()
return LibraryDateMaker.newDate()
end
end
我可能会制作 2 个构造函数,一个采用此接口(interface),另一个使用 RealDateProvider 而无需传入对象的任何生产类。
这是更可取的 OO 做事方式。我想!
2.) 制作您自己的静态日期提供程序,您可以覆盖其行为。
您将 ConfigurableDateMaker.newDate() 设为静态,而不是 LibraryDateMaker.newDate()。它使用与 1 相同的对象,但有一个 setter 允许您根据需要将行为更改为模拟提供者。默认为真实。
这样做的好处是你不必将任何东西传递给你的构造函数,你可以继续使用静态方法进行非常常见的事件。
简而言之,CUT 调用 ConfigurableDateMaker.newDate()。默认情况下返回真实日期,但在您的测试类中,您可以将行为设置为在调用 CUT 之前使用模拟。
class ConfigurableDateMaker
public static DateProvider provider
static date timenow()
return provider.newDate()
end
// add the 2 provider classes as inner classes in here
end
希望这是有道理的。
关于objective-c - 你应该如何在 Objective C/Cocoa 中模拟你不拥有的类? (例如 NSDate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9344051/