PowerMock + Mockito VS 单独 Mockito

发布于 2024-11-07 12:32:55 字数 239 浏览 6 评论 0原文

谁能总结一下,到底有哪些功能可以让您在 Mockito 之上添加 PowerMock?

到目前为止,我已经发现了这些:

  • 模拟静态、最终和私有方法
  • 删除静态初始值设定项
  • 允许在没有依赖项注入的情况下进行模拟-这一点我不清楚。你能详细说明一下吗?

它还添加其他东西吗?你能用几行概括一下吗?

使用 PowerMock 时我需要牺牲一些东西吗?

Can anyone please summarize, what exactly features gives you adding PowerMock on top of the Mockito?

So far I've found these:

  • mock static, final and private methods
  • remove static initializers
  • allow mocking without dependency injection - this one isn't clear to me. Can you elaborate?

Does it add anything else? Can you please sum up in several lines?

And do I need to sacrifice something when using PowerMock?

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

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

发布评论

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

评论(5

兔姬 2024-11-14 12:32:55

我暂时不知道还有其他好处,但我想解决您的两个子问题(对于评论来说这太长了):

允许模拟而不需要依赖注入 - 这个我不清楚。能详细说明一下吗?

我认为这来自 Motivation wiki 页面,其中描述了一种重构代码以不调用静态方法的方法使其可测试。对于我认为他们正在了解的具体示例,假设您有这段代码,并且您想要测试模拟静态方法行为的方法,而不使用 powermock:

public class MyClass {
     public void doGetString() {
         ...
         OtherClass.getString(); //It's complex and scary and needs mocking!
         ...
     }
}

一种解决方案是将静态调用拉入它自己的对象,然后注入一个可以在测试时模拟的对象。例如,在不使用其他框架的情况下,这可能看起来像:

public class MyClass {
     public static class StringGetter {
         public getString() {
             return OtherClass.getString();                 
         }
     }

     private final StringGetter getter;

     //Existing Constructor
     public MyClass() {
         this(new StringGetter());
     }

     //DI Constructor
     MyClass(StringGetter getter) {
         this.getter = getter;
     }

     public void doGetString() {
         ...
         getter.getString();
         ...
     }
}

我已将方法的行为与静态调用的行为分开,并且可以使用 DI 构造函数在测试时轻松注入模拟。当然,使用 powermock,我可以模拟静态方法,然后运行它。

使用 PowerMock 时我需要牺牲一些东西吗?

物理上不,但我想说的是哲学上是:)。以下是我的观点,我试图给出它们背后的充分理由,但当然它们只是观点,所以要持保留态度:

PowerMock 发生的潜在可怕的事情是,为了完成嘲笑的壮举私有和静态方法,它们使用自定义类加载器(不应在生产运行时出现)并更改类的字节码。可以说,在大多数情况下,这对于绝大多数类来说应该无关紧要,但如果您考虑一下,如果字节码已更改,并且某些副作用不再存在,那么您将根据您的情况有效地测试不同的类现有的课程。是的,这是一个非常学术的论点。

您可以通过良好的综合集成和不使用 PowerMock 的更高级别的测试来在一定程度上缓解第一个论点。通过这种方式,即使您的单元测试使用 PowerMock,您也可以对对象的行为更加有信心。

我反对 PowerMock 的另一个论点是,它很容易成为拐杖。我同意 PowerMock 可以帮助测试使用遗留代码和您无法控制的其他代码的代码。但是我认为,当您可以控制需要模拟的类时,您应该避免使用它。如果您编写一个带有私有方法或静态方法的类,您需要显式模拟该方法才能测试其他方法,我的直觉会说这个方法可能做得太多,应该重构和分解。当 PowerMock 已在项目中可用时,您可能会想模拟它并继续前进,这将减轻鼓励您重构相同项目的痛苦。是的,有时由于各种技术和非技术限制,这是不可能的,但解决痛点而不是避免它们是件好事:)

I don't know of other benefits offhand, but I want to address 2 of your sub-questions (and this is way too long for a comment):

allow mocking without dependency injection - this one isn't clear to me. Can you elaborate?

I think this came from the Motivation wiki page where they describe a way of refactoring code to not invoke static methods to make it testable. For a concrete example of what I think they're getting at, let's say you have this code and you want to test the method mocking the behaviour of the static method, without using powermock:

public class MyClass {
     public void doGetString() {
         ...
         OtherClass.getString(); //It's complex and scary and needs mocking!
         ...
     }
}

One solution, would be to pull the static invocation into its own object, then inject an object that can be mocked come test time. For example, without using other frameworks, this could look like:

public class MyClass {
     public static class StringGetter {
         public getString() {
             return OtherClass.getString();                 
         }
     }

     private final StringGetter getter;

     //Existing Constructor
     public MyClass() {
         this(new StringGetter());
     }

     //DI Constructor
     MyClass(StringGetter getter) {
         this.getter = getter;
     }

     public void doGetString() {
         ...
         getter.getString();
         ...
     }
}

I've seperated the behaviour of my method from the behaviour of the static invocation, and can use the DI constructor to inject mocks easily at test time. Of course with powermock I could just mock the static method in place, and run with it.

And do I need to sacrifice something when using PowerMock?

Physically no, but I'd say philosophically yes :). The below are my opinions, and I try to give good reasons behind them, but of course they are opinions so take them with a grain of salt:

The potentially scary thing that is happening with PowerMock is that in order to accomplish the feats of mocking private and static methods, they are using a custom class loader (which shouldn't be present at runtime in production) and changing the bytecode of your classes. Arguably, this should not matter with the vast majority of classes most of the time, but if you think about it, if the bytecode has changed, and certain side effects are no longer present, you're effectively testing different Classes albiet based upon your existing Classes. Yes this is a very academic argument.

You can somewhat mitigate this first argument by having good comprehensive integration and higher level tests that don't use PowerMock. In this way you can be more confident in the behaviours of your objects even if your unit tests are using PowerMock.

The other argument I have against PowerMock, is that it could almost too easily become a crutch. I agree that PowerMock can help with testing code that uses legacy code and other code that you do not have control over. However I would argue that when you have control over the classes that you need to mock, you should avoid its use. If you write a class with a private method or static method that you need to explicitly mock in order to test other methods, my gut instinct would say that this method may be doing too much and should be refactored and broken up. Having PowerMock already available in a project, you may be tempted to just mock it and move on, which would mitigate the pain that should encourage you to refactor the same. Yes there are sometimes due to various technical and non-technical constraints this is not possible, but it's good to solve pain points instead of avoid them :)

裂开嘴轻声笑有多痛 2024-11-14 12:32:55

PowerMock 是 Mockito 的扩展,允许模拟静态方法、构造函数、最终类和方法、私有方法、删除静态初始值设定项等。

PowerMock is an extension to Mockito that allows mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more.

Powermock mockito 扩展的另一个功能是它支持对 equals 和 的模拟和存根哈希码

与所有需要小心使用的 powermock 功能一样,但为特定结果添加(基于值的)相等性可能会有所帮助。

Another feature of the Powermock mockito extension is that it supports mocking and stubbing of equals and hashcode.

As with all powermock features to be used with care, but adding (value-based) equality for specific results can be helpful.

迷雾森÷林ヴ 2024-11-14 12:32:55

PowerMock 的另一个功能是我们可以在方法中模拟新对象的构造。当我们无法更改要测试的方法的代码时,这很有帮助。

One more feature of PowerMock is that we can mock construction of new objects in a method. It is helpful when we cannot change the code of the method to be tested.

纵情客 2024-11-14 12:32:55

为了模拟最终类,我们可以使用 org.mockito.plugins.MockMaker。您需要做的是

  1. test/resource 文件夹中创建一个名为 mockito-extensions 的文件夹。
  2. 在其下创建一个名为 org.mockito.plugins.MockMaker 的文件。
  3. 在该文件中只有一行 mock-maker-inline

这不需要您添加任何新库,从而节省一些运行时间。

For mocking final class we can use org.mockito.plugins.MockMaker. What you would need to do is

  1. Create a folder in your test/resource folder with namemockito-extensions.
  2. Create a file under it with the name org.mockito.plugins.MockMaker.
  3. In that file have just one line mock-maker-inline

This will not require you to do add any new library and hence save some runtime.

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