在为该对象编写类之前为该对象编写模拟/存根?
我正在设计一个具有两个依赖项的类。依赖类之一已编写并测试。另一个还没写。
我突然想到,因为剩下的依赖项将被编写以方便使用它的类,所以我应该先编写后者,然后设计前者的接口,学习它应该做什么。
在我看来,这是编写代码的好方法。毕竟,只要主类在其构造函数中获得模拟,我就可以编写它并测试它,而无需意识到它的依赖项不存在,然后一旦我确定我知道我需要什么,我就可以创建依赖项。
那么:我该怎么做?创建一个骨架类,我会在进行过程中对其进行修改。也许是这样的:
class NonExistantSkeleton
{
public function requiredMethod1()
{
}
public function newlyDiscoveredRequirement()
{
}
}
然后使用 PHPUnit 模拟它,并设置存根等,以使我的类在开发中保持愉快?
这是要走的路吗?
这似乎是一种开发代码的好方法 - 在我看来,这比开发依赖项更有意义,而无需真正确定它将如何使用。
I'm designing a class that has two dependencies. One of the dependency classes has been written and tested. The other has not yet been written.
It has occurred to me because the remaining dependency will be written to facilitate the class that will use it, that I should write the latter first, and design the interface of the former as I go along, learning what it should do.
That seems to me to be a great way to make code. After all, as long as the main class gets a mock in its constructor, I can write it and test it without it being aware that its dependency doesn't exists, then I can create the dependency once I am sure I know what I need.
So: how do I do this? Create a skeleton class that I modify as I go along. Perhaps something like:
class NonExistantSkeleton
{
public function requiredMethod1()
{
}
public function newlyDiscoveredRequirement()
{
}
}
and then mock it using PHPUnit, and setting up stubs, etc, to keep my class under development happy?
Is this the way to go?
It seems like a nice way to develop code - and seems to me to make more sense than developing a dependency, without really knowing for sure how it's going to be used.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
简而言之:
是的。至少这就是我现在正在做的事情。
更长的版本:
如果您的类的预期协作者在您正在构建的类的测试中需要它们的时间点不存在,您有几个选项:
如果你针对接口进行编程无论如何,您需要做的就是创建该接口并告诉 PHPUnit 从它创建一个存根/模拟
当模拟不存在的类时,您会得到一些我不喜欢的缺点:
所以我建议不要这样做。
中间方法是仅使用其方法创建空类骨架并使用它们进行模拟。
在没有界面提示的情况下,我非常喜欢这种方式,因为它速度很快并且可以创建稳定的测试代码。
对我来说,拥有带有公共 API 的准系统类并不违反 TDD。
有些类你不需要模拟。
数据传输对象 和 值对象 始终可以在生产代码中使用
new
在任何地方创建,以便您的测试也可以只是真实的物体。它有助于使您的测试更加干净,因为您不需要模拟/期望大量的 getter/setter 方法等等。
In short:
Yes. At least thats what I'm doing right now.
Longer Version:
If the expected collaborators of your class don't exist at the point in time where you need them in your tests for the class you are building you have a few options:
If you programm against an interface anyways than all you need to do is to create that interface and tell PHPUnit to create a stub/mock from it
When mocking non existing classes you get some drawbacks that I don't like:
so I'd advice against that.
The middle way would be to just create the empty class skeleton with its method and use those for mocking.
I quite like that way in cases where there is no interface to hint against as It is fast and creates stable test code.
Having barebone classes with public apis, for me, is no violation of TDD.
There are classes you don't need to mock.
Data transfer objects and Value Objects can always be created anywhere using the
new
in your production code so your tests also can just the the real objects.It helps to keep your tests a little cleaner as you don't need to mock/expect a lot of getter/setter methods and so on.
如果您遵循测试驱动那么通常的方法如下:
编辑:正如 edorian 指出的那样,PHP 接口在这里提供了巨大的帮助,因为 PHPUnit 可以从接口以及类生成模拟和存根。它们也是减少耦合和提高可替代性的绝佳工具。它们允许您替换任何实现预期接口的类,而不仅仅是预期类的子类。
If you follow a test-driven development methodology then the usual approach is as follows:
EDIT: As edorian pointed out, PHP interfaces are a huge help here because PHPUnit can generate mocks and stubs from interfaces as well as from classes. They're also an excellent tool in reducing coupling and improving substitutability in general. They allow you to substitute any class that implements the expected interface, instead of just subclasses of the expected class.