Come fare a deridere una classe con i metodi finali?
-
07-07-2019 - |
Domanda
Dire che ho classe A con
class A {
final String foo() {
// .. computing result, contacting database, whatever ..
return "some computed value";
}
// ... and a bazillion other methods, some of them final.
}
Ora ho classe B con
class B {
String methodIWantToTest(A a) {
String output = a.foo();
// ... whatever this method does, e.g.:
output += "_suffix";
return output;
}
}
Come potrei fare per testare l'unità questo metodo? La ragione per cui foo ()
è definitiva perché non vogliamo che le nostre classi che estendono A cambino la sua funzionalità. Allo stesso tempo, per testare veramente il metodo, non voglio che raggiunga ed esegua l'attuale metodo A.foo ()
.
C'è un modo, per esempio, di rimuovere la parola chiave finale e aggiungere un'annotazione lungo le linee di @finalUnlessTest
? Cosa raccomanderesti? Rifattorizzare A su un'interfaccia sarebbe molto, molto difficile, visto che è una delle nostre classi centrali ed è purtroppo carina estremamente accoppiata.
Modifica n. 1 Siamo spiacenti, ho dimenticato di menzionare, stiamo parlando di Java. Non stiamo ancora utilizzando un framework beffardo.
Rispondi OK, quindi: wow. JMockit è semplicemente incredibile ed è ai miei occhi l'app killer per testare il codice legacy. Incredibilmente utile soprattutto nel mio caso. Grazie mille! Fondamentalmente faresti qualcosa di simile al mio esempio 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));
}
}
È fottutamente bello o cosa?
Soluzione
Puoi provare la JMockit libreria di derisione.
Altri suggerimenti
Rimuoverei " final " e inserisci un commento " Non sovrascrivere questo metodo !! " ;. Se non puoi fidarti dei colleghi che non seguono semplici istruzioni, è comunque senza speranza.
Il seguente codice ti permetterà anche di farlo. Non sto dicendo che questa è una buona pratica, ma è un uso interessante (abuso?) Di classi anonime.
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() );
}
}