Como zombar de uma aula com métodos finais?
-
07-07-2019 - |
Pergunta
Diga que tenho classe A com
class A {
final String foo() {
// .. computing result, contacting database, whatever ..
return "some computed value";
}
// ... and a bazillion other methods, some of them final.
}
Agora eu tenho classe B com
class B {
String methodIWantToTest(A a) {
String output = a.foo();
// ... whatever this method does, e.g.:
output += "_suffix";
return output;
}
}
Como eu iria testar esse método? A razão foo()
é final é porque não queremos nossas classes que estendam A para alterar sua funcionalidade. Mas, ao mesmo tempo, para verdadeiramente o teste de unidade do método, não quero que ele estejam alcança e execute o real A.foo()
método.
Existe uma maneira de, digamos, remover a palavra -chave final e adicionar uma anotação ao longo das linhas de @finalUnlessTest
? O que você recomendaria? Refatorar A a uma interface seria muito, muito difícil, visto como é uma de nossas classes centrais e infelizmente bonito extremamente acoplado.
Editar #1 Desculpe, esqueci de mencionar, estamos falando de Java. Ainda não estamos usando uma estrutura de zombaria.
Responda OK, então: uau. Jmockit é simplesmente incrível e está aos meus olhos o aplicativo assassino para testar o código legado. Inacreditavelmente útil, especialmente no meu caso. Muito obrigado! Você basicamente faria algo como o seguinte para o meu exemplo de PSUDO:
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));
}
}
Isso é legal ou o quê?
Solução
Você pode tentar o Jmockit Biblioteca zombeteira.
Outras dicas
Eu removeria o "final" e apenas colocava um comentário "Não substitua esse método !!". Se você não pode confiar nos colegas de trabalho para não seguir instruções simples, é inútil de qualquer maneira.
O código a seguir também permitirá que você o faça. Não estou dizendo que isso é uma boa prática, mas é um uso interessante (abuso?) De aulas anônimas.
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() );
}
}