【问题标题】:Changing Final field using mockito使用 mockito 更改 Final 字段
【发布时间】:2019-09-12 05:03:25
【问题描述】:

我在模拟课程的最后一个字段时遇到了 mockito 问题,你们能帮忙解决一下吗

public class Product{
  public final String VALUE= "ABC";

  public String someMethod(){
      if (!VALUE.equals("ABC")){ ## IF NOT WORKING
         //inside if condition
      }else{
         //inside else condition
      }
  }

}

//Test Class
@test
public void test_someMethod(){
    Product product = Mockito.mock(Product.class,"Product");

    Field field = Product.class.getDeclaredField("VALUE");
    field.setAccessible(true);

    ReflectionUtils.setField(field, product , "XYZ");

 }

现在,当在调试模式下运行时,这显示我将值更改为 XYZ,但不使用 if 条件总是进入 else 块,尽管在调试模式下显示 XYZ。

【问题讨论】:

    标签: java mockito junit5 powermockito


    【解决方案1】:

    基本上,你在这里走错了兔子洞。将这么多东西放在一起不是一个好主意。

    首先,Mockito(和所有其他模拟框架)旨在用于行为,而不是状态。换句话说。尽管您的模拟对象实际上具有该字段,但请记住:它仍然是模拟对象。您不会找到太多的文档或教程来告诉您模拟框架将如何处理字段以及模拟对象的字段值。

    更糟糕的是,真正的问题:你没有模拟你的被测类。您使用模拟来控制您的测试代码正在使用的 other 对象。模拟和测试同一个对象根本没有(太多)意义!

    然后:不要将反射与基于“模拟”的单元测试一起使用,尤其是不要在模拟对象上“反射”。如前所述:这些框架会做任何他们认为必要的事情,因此即使某些代码现在可以工作,新版本的 Mockito 也有可能会改变此类内部结构,并导致此类代码在未来失败。

    接下来,请注意您的代码是荒谬的

    public final String VALUE= "ABC";
    public String someMethod(){
      if (!VALUE.equals("ABC")){ ## IF NOT WORKING
    

    VALUE 始终为 ABC,因此您始终以 if(!true) 结尾。那么在您的代码中使用该 if 语句是没有意义的。

    所以,如果您真的需要这种开关,您可以将其设为方法调用,例如:

      public String someMethod(){
        if (reallyDoIt())) ...
    

     boolean reallyDoIt() { return ...
    

    重点是:现在您可以使用 Mockito 的间谍概念来测试您的 someMethod() 呼叫。通过这样做,您可以指示 Mockito “真正地”调用 someMethod(),但返回 reallyDoIt() 的虚假答案。更多详情,请参阅here 示例。

    除此之外,我强烈建议您退后一步,阅读一篇关于 Mockito 的优秀教程,例如来自 vogella 的教程。仅仅因为您的代码暗示您并不真正了解如何在单元测试中使用模拟框架。

    【讨论】:

      【解决方案2】:

      谢谢.. 详细的解释。但对我来说,这里的限制是不要更改基本代码(即 somemethod())。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-24
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        • 2018-03-17
        • 1970-01-01
        • 1970-01-01
        • 2021-06-30
        相关资源
        最近更新 更多