部分嘲笑是代码异味?

发布于 2024-09-25 06:58:00 字数 640 浏览 7 评论 0原文

为什么对“部分模拟”和需要它的代码有如此多的仇恨?

这是一个(理论上的)示例实现:

public ComplexResult1 operationA(Stimulus a) {
    {
        ...
        result = ...;
    }
    auditTheChange(a);
}
public ComplexResult2 operationB(Stimulus b) {
    {
        ...
        result = ...;
    }
    auditTheChange(b);
    return result;
}
void auditTheChange(Stimulus stim) {
    // do a bunch of stuff to record the change
    // and interact with another outside service
}

现在,根据我的理解,这是经过良好重构的代码。

如果我想对操作A和操作B进行UNIT测试,确保在每个场景中都进行审核,但无需测试审核代码的细节,我将使用部分模拟。

我没有看到/理解什么导致这么多项目(EasyMock、Mockito 等)建议重构?

Why is there so much hating going on about 'partial mocking' and the code that requires it?

Here's an (theoretical) example implementation:

public ComplexResult1 operationA(Stimulus a) {
    {
        ...
        result = ...;
    }
    auditTheChange(a);
}
public ComplexResult2 operationB(Stimulus b) {
    {
        ...
        result = ...;
    }
    auditTheChange(b);
    return result;
}
void auditTheChange(Stimulus stim) {
    // do a bunch of stuff to record the change
    // and interact with another outside service
}

Now, in my understanding this is well refactored code.

If I want to UNIT test operationA and operationB, and ensure that auditing happens in each scenario, but without having to test the specifics of the audit code, I would use partial mocking.

What am I not seeing/understanding that causes so many projects (EasyMock, Mockito, etc.) to recommend refactoring?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伤感在游骋 2024-10-02 06:58:00

如果审核确实是类的内部功能,那么应该将代码作为单元测试的一部分进行测试。为什么你的类要处理复杂的操作和审计?审计可以转移到一个单独的班级吗?

如果是这样,请以此类的合作者身份引入审核并模拟它。如果没有,请对其进行单元测试。

您可以使用部分模拟,但在这种情况下,我认为这表明该类做得太多了。

If auditing is truly an internal function of the class then the code should be tested as part of the unit test. Why does your class handle both complex operations and auditing? Could the auditing be moved to a separate class?

If so, introduce the auditing as a collaborator with this class and mock it out. If not, unit test it.

You can use partial mocks, but in this case I think it is an indication the class is doing too much.

鸠书 2024-10-02 06:58:00

如果auditTheChange是私有函数,那么您就不需要编写验证其调用的测试。
您不希望单元测试与实现紧密耦合。

一般来说:不要对私有方法进行单元测试

If auditTheChange is a private function, then you just don't write a test which verifies its invocation.
You don't want your unit test be tightly coupled to an implementation.

And just in general: Don't unit test private methods.

浪荡不羁 2024-10-02 06:58:00

关键点是“被测试的单元是什么”。

许多开发人员认为是面向对象的。在OO中,“对象”是软件的单位,因此对象也是单元测试中被测试的单位。在您的示例中,auditTheChange() 是对象中的私有方法。单元测试应该只关注公共方法的行为。模拟私有方法意味着处理单元的某些实现细节的单元测试用例被视为“代码味道”。

一些开发人员认为软件的单位是“方法”。在你的例子中,你确实是这样想的。由于操作A和操作B过于复杂,因此您创建auditTheChange,以便可以降低单元操作A和操作B的复杂性。如果您这样认为,部分模拟就不是“代码味道”,因为该方法是一个正在测试的单元,模拟私有方法也意味着“关注行为,而不是实现细节”。

这里没有绝对的对或错。这实际上取决于您的项目或团队的性质。我在一家使用 Spring 开发企业信息系统的公司工作。在Spring中,几乎所有的业务逻辑都是在xxxService对象中实现的。当方法太复杂时,我们只需将一些逻辑移至私有方法,就像您在示例中所做的那样。如果我们总是将该逻辑移至新类,则会创建大量类和对象,这将使程序难以维护。因此,我们只是将逻辑移至私有方法并使用部分模拟。事实上,很多人都需要部分模拟。您可以检查这个 Mockito< /a> 文档。一开始,mockito 认为部分模拟是一种代码味道。经过长时间的讨论和辩论,他们现在也支持部分模拟。

The key point is "what is the unit being tested".

A lot of developers think OO. In OO, "object" is the unit of software so that object is also the unit that is tested in the unit test. In your example, auditTheChange() is a private method in an object. A unit test should focus on the behavior of public method only. Mock a private method means the unit test case dealing with some implementation detail of the unit which is considered as a "code smell".

Some developers think the unit of software is "method". In your example, you do think in this way. Because operationA and operationB is too complicated so that you create auditTheChange so that the complexity of unit operationA and operationB can be reduced. If you think in this way, partial mocking is not a "code smell" because the method is a unit being tested and mocking a private method also means "focus on behavior, not implementation details".

There is no absolute right or wrong here. It really depends on the nature of your project or team. I worked for a company developing an enterprise info system using Spring. In Spring, almost all business logic is implemented in xxxService objects. When a method is too complicated, we just move some logic to a private method as you did in your example. If we always move that logic to a new class, there will be a lot of classes and objects will be created and that will make the programs difficult to maintain. So, we just moved the logic to private methods and used partial mocks. Actually, a lot of people needed partial mocks. You can check this Mockito document. At the beginning, mockito thinks partial mock is a code smell. After a long discussion and debate, they also support partial mocks now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文