如何用最终方法嘲笑一个类?

时间:2023-01-27 12:40:40

Say I have class A with

说我有A级

class A {
  final String foo() {
    // .. computing result, contacting database, whatever ..
    return "some computed value";
  }
  // ... and a bazillion other methods, some of them final.
}

Now I have class B with

现在我有B级

class B {
  String methodIWantToTest(A a) {
      String output = a.foo();
      // ... whatever this method does, e.g.:
      output += "_suffix";
      return output;
  }
}

How would I go about unit testing this method? The reason foo() is final is because we don't want our classes which extend A to change its functionality. But at the same time to truly unit test the method, I don't want it to reach out and run the actual A.foo() method.

我如何进行单元测试这种方法? foo()是final的原因是因为我们不希望扩展A的类改变其功能。但同时要真正对该方法进行单元测试,我不希望它伸出并运行实际的A.foo()方法。

Is there a way to, say, remove the final keyword and add an annotation along the lines of @finalUnlessTest? What would you recommend? Refactoring A to an interface would be very, very difficult, seeing as how it's one of our central classes and is unfortunately pretty extremely coupled.

有没有办法,比如删除final关键字并在@finalUnlessTest的行中添加注释?你会推荐什么?重构A到一个接口将是非常非常困难的,看它是如何它是我们的中心类之一,并且不幸的是非常非常耦合。

Edit #1 Sorry, forgot to mention, we're talking Java. We are not using a mocking framework as of yet.

编辑#1抱歉,忘记提及,我们正在谈论Java。我们还没有使用模拟框架。

Answer OK, so: wow. JMockit is just incredible and is in my eyes the killer app for testing legacy code. Unbelievably useful especially in my case. Thanks so much! You basically would do something like the following for my psuedo-example:

回答好的,所以:哇。 JMockit是令人难以置信的,在我看来是测试遗留代码的杀手级应用程序。特别是在我的情况下,令人难以置信的有用。非常感谢!对于我的psuedo-example,你基本上会做类似下面的事情:

class AMock {
   final String foo() {
     return "myTestValue";
   }
}
class Test extends TestCase {
   A mockedA;
   B b;
   protected void setUp() {
      Mockit.redefineMethods( A.class, AMock.class );  // this "pipes" all mocked methods from A to AMock
      mockedA = new A();    // NOT new AMock()!!!
      b = new B();
   }
   public void testB() {
      assertEquals("myTestValue",mockedA.foo());
      assertEquals("myTestValue_suffix",b.methodIWantToTest(mockedA));
   }
}

Is this frickin' cool or what?

这个frickin'酷还是什么?

3 个解决方案

#1


6  

You can try the JMockit mocking library.

您可以尝试使用JMockit模拟库。

#2


0  

I'd remove the "final" and just put in a comment "Don't override this method!!". If you can't trust coworkers not to follow simple instructions, it's hopeless anyway.

我将删除“最终”并只是发表评论“不要覆盖此方法!!”。如果你不能相信同事不遵循简单的指示,那么无论如何都是无望的。

#3


0  

The following code will also allow you to do it. I am not saying that this is good practice, but it is an interesting use (abuse?) of anonymous classes.

以下代码也允许您这样做。我并不是说这是一种很好的做法,但它是一种有趣的使用(滥用?)的匿名类。

public class Jobber {

    public final String foo() {
        return fooFactory() ;
    }

    String fooFactory() {
        return "jobber" ;
    }


    public static void main(String[] args) {

        Jobber jobber = new Jobber() { String fooFactory() { return "prefix " + super.fooFactory() ;} } ;

        System.out.println(jobber.foo() );
    }
}

#1


6  

You can try the JMockit mocking library.

您可以尝试使用JMockit模拟库。

#2


0  

I'd remove the "final" and just put in a comment "Don't override this method!!". If you can't trust coworkers not to follow simple instructions, it's hopeless anyway.

我将删除“最终”并只是发表评论“不要覆盖此方法!!”。如果你不能相信同事不遵循简单的指示,那么无论如何都是无望的。

#3


0  

The following code will also allow you to do it. I am not saying that this is good practice, but it is an interesting use (abuse?) of anonymous classes.

以下代码也允许您这样做。我并不是说这是一种很好的做法,但它是一种有趣的使用(滥用?)的匿名类。

public class Jobber {

    public final String foo() {
        return fooFactory() ;
    }

    String fooFactory() {
        return "jobber" ;
    }


    public static void main(String[] args) {

        Jobber jobber = new Jobber() { String fooFactory() { return "prefix " + super.fooFactory() ;} } ;

        System.out.println(jobber.foo() );
    }
}