mocks are definitely useful in unit testing. When you want to test A that relies on B, in isolation, then you mock B (with expected input/output) to test A. You make sure you test B separately to make sure it is correct.
In dynamic languages, they aren't strictly necessary. But mocking frameworks can help you verify that the expectations you set on the mock are met.
You should never use a mock as a real implementation. That type of thing is the stuff of jokes. "We can just mock the entire application! Yaaaaay!" Thats what interfaces/equivalent are for...
Ultimately, it can be argued that it is "just another way to do it." Software was written for decades and continues to be written in the absence of mocking.
It is primarily a facility of unit testing.
Where mocking/stubs really shine is test-driven development. The problem one faces in the absence of mocking/stubbing is that the web of dependencies in an application is often such that you have to build almost the entire application before you can write tests, and even then you're testing larger sections of functionality, such that isolating bugs becomes more difficult.
Consider the following:
I want to create ClassA and write tests to verify its behaviour.
I start writing the test (test-first to drive out the design).
Oops, ClassA needs to get data from RepositoryM.
I'll implement RepositoryM so that I can test ClassA.
Oh, but first let's write tests for RepositoryM.
Darn, RepositoryM really needs ServiceX to populate its data.
I'll implement ServiceX so I can test and implement RepositoryM so I can test and implement ClassA
…and on and on.
Using mocks allows you to start writing tests without implementing anything. All you need are interfaces.
Using a mocking framework makes test construction much faster.
Mocking/stubbing has ancillary benefits -- one of which is enforcement of programming to abstractions instead of implementations.
Would you guys say that the use of mocks is better than not using mocks?
Is driving a motorbike better than driving a car? It depends what you're trying to achieve :).
Why use mocks?
Mocks versus state-based testing: While I generally like state-based testing because it feels more solid/straight forward, it's often the case that using mocks is the only way to verify that a unit of code performs its role correctly. Why? Well, when designing with the tell, don't ask principle in mind, classes often do not expose enough data to verify your expectations, so the only way to verify it's working properly is to check its behaviour/interactions with other collaborators.
A good example is a class that sends emails when an order is finalised -- the class won't have a "number of emails sent" property or anything similar, so you need to check that the appropriate method call was made. Mocks set expectations on the interactions.
While you can test the interactions by hand-rolling your own test double classes that expose this data (e.g. create a type that implements the required interface, then push method call information into a list, then assert against the stored state), mocking frameworks speed up the process by allowing us to only fill in the bits we actually care about.
Should I use mocks in production code?
Is mocking used only in unit testing or could it be used directly in the original project as the real object and switch it after?
If by "mocking" you mean using a "a 'fake' type that can be swapped in and behave in a sensible manner", then yes -- I've often used 'fake' types such as an in memory dictionary to substitute for database connections and so forth. They can act as a useful stopgap in non-live production code.
Similarly, if you program to an interface, you can create a working skeleton of an application with stubbed out functionality. This helps get a full programming structure fleshed out without having to focus on details. You can substitute in the real implementation once it's available (though expect some integration errors if you're not backed by integration tests).
If, on the other hand, by "mocking" you mean "using a mocking framework in the production code", then no -- I wouldn't recommend doing that, I'd hand-write the fake implementations and stay free of the dependency, plus it'll be easier to reason about and debug.
发布评论
评论(3)
模拟在单元测试中绝对有用。当您想要单独测试依赖于 B 的 A 时,您可以模拟 B(使用预期的输入/输出)来测试 A。您确保单独测试 B 以确保它是正确的。
在动态语言中,它们并不是绝对必要的。但是模拟框架可以帮助您验证您对模拟设定的期望是否得到满足。
您永远不应该使用模拟作为真正的实现。这类事情简直就是笑话。 “我们可以模拟整个应用程序!Yaaaaay!”这就是接口/等效项的用途......
mocks are definitely useful in unit testing. When you want to test A that relies on B, in isolation, then you mock B (with expected input/output) to test A. You make sure you test B separately to make sure it is correct.
In dynamic languages, they aren't strictly necessary. But mocking frameworks can help you verify that the expectations you set on the mock are met.
You should never use a mock as a real implementation. That type of thing is the stuff of jokes. "We can just mock the entire application! Yaaaaay!" Thats what interfaces/equivalent are for...
最终,可以说这“只是另一种实现方式”。软件已经编写了几十年,并且在没有模拟的情况下继续编写。
它主要是单元测试的工具。
模拟/存根真正发挥作用的是测试驱动开发。在没有模拟/存根的情况下面临的问题是,应用程序中的依赖网络通常是这样的,您必须先构建几乎整个应用程序,然后才能编写测试,即使这样您也要测试更大的功能部分,这样隔离错误就变得更加困难。
考虑以下事项:
ClassA
需要从RepositoryM
获取数据。RepositoryM
,以便可以测试ClassA
。RepositoryM
编写测试。RepositoryM
确实需要ServiceX
来填充其数据。ServiceX
,这样我就可以测试和实现RepositoryM
,这样我就可以测试和实现ClassA
...等等。
使用模拟可以让您开始编写测试而无需实现任何内容。您所需要的只是接口。
使用模拟框架可以使测试构建更快。
模拟/存根具有附带的好处——其中之一是对抽象而不是实现进行编程。
Ultimately, it can be argued that it is "just another way to do it." Software was written for decades and continues to be written in the absence of mocking.
It is primarily a facility of unit testing.
Where mocking/stubs really shine is test-driven development. The problem one faces in the absence of mocking/stubbing is that the web of dependencies in an application is often such that you have to build almost the entire application before you can write tests, and even then you're testing larger sections of functionality, such that isolating bugs becomes more difficult.
Consider the following:
ClassA
and write tests to verify its behaviour.ClassA
needs to get data fromRepositoryM
.RepositoryM
so that I can testClassA
.RepositoryM
.RepositoryM
really needsServiceX
to populate its data.ServiceX
so I can test and implementRepositoryM
so I can test and implementClassA
…and on and on.
Using mocks allows you to start writing tests without implementing anything. All you need are interfaces.
Using a mocking framework makes test construction much faster.
Mocking/stubbing has ancillary benefits -- one of which is enforcement of programming to abstractions instead of implementations.
驾驶摩托车比驾驶汽车更好吗?这取决于您想要实现的目标:)。
为什么使用模拟?
模拟与基于状态的测试:虽然我通常喜欢基于状态的测试,因为它感觉更可靠/直接,但通常情况下,使用模拟是验证测试是否正确的唯一方法。代码单元正确地发挥其作用。为什么?好吧,在设计时牢记告诉,不要问原则,课程经常不要公开足够的数据来验证您的期望,因此验证其正常工作的唯一方法是检查其与其他协作者的行为/交互。
一个很好的例子是一个在订单完成时发送电子邮件的类 - 该类不会有“发送的电子邮件数量”属性或任何类似的属性,因此您需要检查是否进行了适当的方法调用。模拟设定了对交互的期望。
虽然您可以通过手动滚动公开此数据的自己的测试双类来测试交互(例如,创建一个实现所需接口的类型,然后将方法调用信息推送到列表中,然后针对存储的状态进行断言),但模拟框架速度通过允许我们只填写我们真正关心的部分来加快流程。
我应该在生产代码中使用模拟吗?
如果“嘲笑”你的意思是使用“可以交换并以合理方式运行的‘假’类型”,那么是的——我经常使用‘假’类型,例如内存中的字典来替代数据库连接等。它们可以作为非实时生产代码中有用的权宜之计。
同样,如果您对接口进行编程,则可以创建具有已存根功能的应用程序的工作框架。这有助于充实完整的编程结构,而不必关注细节。一旦可用,您就可以在实际实现中进行替换(尽管如果您没有集成测试的支持,预计会出现一些集成错误)。
另一方面,如果“模拟”是指“在生产代码中使用模拟框架”,那么不——我不建议这样做,我会手写假实现并远离依赖性,而且更容易推理和调试。
Is driving a motorbike better than driving a car? It depends what you're trying to achieve :).
Why use mocks?
Mocks versus state-based testing: While I generally like state-based testing because it feels more solid/straight forward, it's often the case that using mocks is the only way to verify that a unit of code performs its role correctly. Why? Well, when designing with the tell, don't ask principle in mind, classes often do not expose enough data to verify your expectations, so the only way to verify it's working properly is to check its behaviour/interactions with other collaborators.
A good example is a class that sends emails when an order is finalised -- the class won't have a "number of emails sent" property or anything similar, so you need to check that the appropriate method call was made. Mocks set expectations on the interactions.
While you can test the interactions by hand-rolling your own test double classes that expose this data (e.g. create a type that implements the required interface, then push method call information into a list, then assert against the stored state), mocking frameworks speed up the process by allowing us to only fill in the bits we actually care about.
Should I use mocks in production code?
If by "mocking" you mean using a "a 'fake' type that can be swapped in and behave in a sensible manner", then yes -- I've often used 'fake' types such as an in memory dictionary to substitute for database connections and so forth. They can act as a useful stopgap in non-live production code.
Similarly, if you program to an interface, you can create a working skeleton of an application with stubbed out functionality. This helps get a full programming structure fleshed out without having to focus on details. You can substitute in the real implementation once it's available (though expect some integration errors if you're not backed by integration tests).
If, on the other hand, by "mocking" you mean "using a mocking framework in the production code", then no -- I wouldn't recommend doing that, I'd hand-write the fake implementations and stay free of the dependency, plus it'll be easier to reason about and debug.