publicos privada modificadores metodos especificadores clase atributo acceso java junit

java - privada - ¿Cómo puedo probar los métodos finales y estáticos de un proyecto de utilidad?



modificadores de acceso pdf (6)

Estoy intentando implementar pruebas unitarias para un proyecto, usa un proyecto de "utilidad" heredado que está lleno de métodos estáticos y muchas de las clases son definitivas o sus métodos son definitivos. No puedo actualizar el proyecto heredado en absoluto.

JMock y EasyMock se ahogan con los métodos finales, y no veo una buena manera de probar las llamadas estáticas. ¿Qué técnicas hay para probarlas?


¿Qué tal un nivel de inyección indirecta / dependencia?

Dado que el proyecto de utilidad heredada es su dependencia, cree una interfaz para separarlo de su código. Ahora su implementación real / de producción de esta interfaz se delega a los métodos de utilidad heredados.

public LegacyActions : ILegacyActions { public void SomeMethod() { // delegates to final/static legacy utility method } }

Para sus pruebas, puede crear un simulacro de esta interfaz y evitar interactuar con la herramienta de utilidad heredada.


Como ya se señaló, se puede utilizar JMockit . Un ejemplo:

@Test public void mockStaticAndFinalMethods(final LegacyService mock) { new NonStrictExpectations() { { LegacyService.staticMethod("hello"); result = "Hello altered World"; } }; String actual = LegacyService.staticMethod("hello"); new LegacyService().finalMethod(123, "test"); assertEquals("Hello altered World", actual); new Verifications() { { mock.finalMethod(123, "test"); // verify this call occurred at least once } }; }

La página de inicio del proyecto JMockit contiene una comparación con PowerMock, para aquellos interesados.


JMock junto con JDave puede simular métodos y clases finales, si es necesario. Here hay instrucciones. Dicho esto, trataría este código heredado (como otros ya han sugerido) como una dependencia externa y crear interfaces y simularlos. Es otra capa de direccionamiento indirecto, pero como no puede cambiar ese código heredado, parece ser razonable.


Si puede refactorizar su código, puede ajustar sus llamadas a los métodos finales / estáticos en métodos de instancia simples, por ejemplo:

protected Foo doBar(String name) { return Utility.doBar(name); }

Esto le permite anular su método de envoltura en la prueba de unidad para devolver una instancia simulada de Foo.

Alternativamente, puede usar Powermock , que extiende Easymock (y Mockito) para permitir la burla de los métodos finales y estáticos:

PowerMock es un marco que extiende otras bibliotecas simuladas, como EasyMock, con capacidades más potentes. PowerMock utiliza un cargador de clases personalizado y la manipulación de bytecode para permitir el simulacro de métodos estáticos, constructores, clases finales y métodos, métodos privados, eliminación de inicializadores estáticos y más.

Aquí hay un example prueba burlándose de un método final estático, el ejemplo muestra cómo burlarse de otros tipos también:

@Test public void testMockStaticFinal() throws Exception { mockStatic(StaticService.class); String expected = "Hello altered World"; expect(StaticService.sayFinal("hello")).andReturn("Hello altered World"); replay(StaticService.class); String actual = StaticService.sayFinal("hello"); verify(StaticService.class); assertEquals("Expected and actual did not match", expected, actual); // Singleton still be mocked by now. try { StaticService.sayFinal("world"); fail("Should throw AssertionError!"); } catch (AssertionError e) { assertEquals("/n Unexpected method call sayFinal(/"world/"):", e.getMessage()); } }


Si su método no refactorable usa algo como JNDI para conectarse a otro servicio, consideraría iniciar un servicio JDNI y poblarlo con los apéndices que usted controla. Es un dolor pero relativamente sencillo. Puede significar configurar una base de datos o un oyente JMS o lo que sea, pero debe haber una implementación java ligera que pueda incluir en las pruebas.


JMockit te permite JMockit métodos estáticos y clases finales. Supongo que utiliza algún classloadin-fu, aunque realmente no lo he investigado.

JMockit Expectations API permite establecer expectativas en cualquier tipo de invocación de método (en interfaces, clases abstractas, clases finales concretas o no finales y en métodos estáticos), así como en la creación de instancias de clase a través de cualquier constructor.