Java 如何使用final方法模拟类?

Java 如何使用final方法模拟类?,java,unit-testing,mocking,legacy-code,Java,Unit Testing,Mocking,Legacy Code,说我和你有一个班级 class A { final String foo() { // .. computing result, contacting database, whatever .. return "some computed value"; } // ... and a bazillion other methods, some of them final. } 现在我有了B班 class B { String methodIWantToTest(

说我和你有一个班级

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

class B {
  String methodIWantToTest(A a) {
      String output = a.foo();
      // ... whatever this method does, e.g.:
      output += "_suffix";
      return output;
  }
}
我如何进行这种方法的单元测试?之所以
foo()
是最终原因,是因为我们不想让扩展了的类更改其功能。但同时为了真正地对该方法进行单元测试,我不希望它接触并运行实际的
A.foo()
方法

有没有办法,比如说,删除最后一个关键字,并按照
@finalUnlessTest
添加注释?你推荐什么?重构一个接口将是非常非常困难的,因为它是我们的中心类之一,不幸的是,它是非常耦合的

编辑#1对不起,忘了提一下,我们说的是Java。到目前为止,我们还没有使用模拟框架

回答好,那么:哇。这是难以置信的,在我看来是测试遗留代码的杀手级应用。难以置信的有用,尤其是对我来说。非常感谢!对于我的psuedo示例,您基本上会执行以下操作:

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));
   }
}

这真是太酷了还是怎么了?

我会删除“final”并添加一条注释“不要重写此方法!!”。如果你不能相信同事们不会按照简单的指示去做,那就没有希望了。

你可以试试模拟库

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

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() );
    }
}

从资本化的角度来看,这一定是Java。你能告诉我们你使用什么语言(看起来像Java)吗?有些答案可能取决于语言,还可以告诉我们您使用的模拟框架…除了我们谈论的不仅仅是同事,因为客户可以使用我们的API…嗯。在没有给出理由的情况下记下这一点似乎很苛刻。我想我不应该把这些事情当回事。这里有一篇有趣的文章讨论了这种测试对象的策略。。。