mock method example java unit-testing junit mocking powermock

java - example - powermock static method



Error en junit mientras se burlaba (2)

Aquí está mi código de trabajo:

import static org.junit.Assert.assertEquals; import java.util.HashMap; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(CollectionUtil.class) public class TestHarnesTest { @InjectMocks TestHarnes w_res = new TestHarnes(); @Before public void before() { PowerMockito.mockStatic(CollectionUtil.class); } @Test public void test_removeHashedSettings() throws Exception { HashMap<String, String> w_abc = new HashMap<String, String>(); w_abc.put("abc", "89"); // CollectionUtil mock = org.mockito.Mockito.mock(CollectionUtil.class); // PowerMockito.mockStatic(CollectionUtil.class,w_abc); PowerMockito.when(CollectionUtil.createHashMap(Mockito.eq("abc:89"), Mockito.eq(":"))).thenReturn(w_abc); assertEquals("abc:89:", TestHarnes.removeHashedSettings("1", "abc:89", ":")); } }

y la clase TestHarnes

public class TestHarnes { public static String removeHashedSettings(final String key, final String a_settings, final String deilimiter) throws Exception { if (!(key != null && key.trim().length() > 0)) { return a_settings; } if (!(a_settings != null && a_settings.trim().length() > 0)) { return a_settings; } HashMap hSettings = CollectionUtil.createHashMap(a_settings, deilimiter); hSettings.remove(key); return getSettingFromHash(hSettings, deilimiter); } private static String getSettingFromHash(final HashMap hSettings, final String deilimiter) { return ""; } }

Soy nuevo en Junit, a continuación se muestra el código junit que estoy ejecutando.

package com.de.base.util.general; import static org.junit.Assert.*; import static org.mockito.Mockito.when; import java.util.HashMap; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.powermock.api.mockito.PowerMockito; @RunWith(MockitoJUnitRunner.class) public class JReportUtilTest { @InjectMocks ReportUtil w_res = new ReportUtil(); @Mock CollectionUtil w_util; @Test public void test_removeHashedSettings() throws Exception { HashMap<String ,String> w_abc = new HashMap<String,String>(); w_abc.put("abc","89"); //CollectionUtil mock = org.mockito.Mockito.mock(CollectionUtil.class); //PowerMockito.mockStatic(CollectionUtil.class,w_abc); when(w_util.createHashMap("abc:89", ":")).thenReturn(w_abc); assertEquals("abc:89:",ReportUtil.removeHashedSettings("1", "abc:89", ":")); } }

Aquí está mi api removedHashedSettingsin ReportUtil

public static String removeHashedSettings(String key, String a_settings, String deilimiter) throws Exception { if (!(key != null && key.trim().length() > 0)) return a_settings; if (!(a_settings != null && a_settings.trim().length() > 0)) return a_settings; HashMap hSettings = CollectionUtil.createHashMap(a_settings, deilimiter); hSettings.remove(key); return getSettingFromHash(hSettings, deilimiter); }

A continuación se muestra el código para createHashMap en CollectionUtil que tengo que burlar.

public static HashMap<String, String> createHashMap(String a_NameValStr, String a_Delim)// throws Exception { HashMap<String, String> w_KeyVal = new HashMap<String, String>(); if (LOGGER.isInfoEnabled()) LOGGER.info("CollectionUtil:createHashMap:Hashing string: "+ a_NameValStr ); if(a_NameValStr == null) return w_KeyVal; StringTokenizer w_StrTkn = new StringTokenizer(a_NameValStr, a_Delim); if( w_StrTkn.countTokens() == 0 || (w_StrTkn.countTokens()%2) != 0 ) { LOGGER.warn("CollectionUtil:createHashMap:Invalid number of tokens to hash: "+ a_NameValStr+":"+w_StrTkn.countTokens() ); return w_KeyVal; } while (w_StrTkn.hasMoreTokens()) w_KeyVal.put( w_StrTkn.nextToken(), w_StrTkn.nextToken()); System.out.println(w_KeyVal); return w_KeyVal; }

Aquí está el error que estoy obteniendo al ejecutar mi caso de prueba junit.

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be ''a method call on a mock''. For example: when(mock.getArticles()).thenReturn(articles); Also, this error might show up because: 1. you stub either of: final/private/equals()/hashCode() methods. Those methods *cannot* be stubbed/verified. Mocking methods declared on non-public parent classes is not supported. 2. inside when() you don''t call method on mock but on some other object. at com.de.base.util.general.JReportUtilTest.test_removeHashedSettings(JReportUtilTest.java:32) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Estoy usando mockito -all-1.10.19.jar, powermock-api-mockito-1.6.6.jar, powermock-core-1.6.6.jar, powermock-module-junit4-1.6.6.jar ¿Alguien me puede ayudar ¿para resolver este problema?


No usas el corredor de PowerMock:

@RunWith(PowerMockRunner.class)

Mockito no puede simular el método estático, pero PowerMock sí.

Y deberías burlarte de la clase con el método estático:

PowerMockito.mockStatic(CollectionUtil.class);

De todos modos, un mejor diseño está reemplazando el método estático por un método de instancia.
Los métodos estáticos no se pueden probar de forma natural y obligan a crear una solución compleja y no legible.
Por ejemplo, observe la complejidad de la combinación de dependencias necesarias para probar una clase simple.

Debe mantener el uso de métodos estáticos como ayudante que no ejecutan la lógica central del dominio y que no necesitan burlarse .

Cuando los métodos realizan la lógica del núcleo del dominio como es el caso del createHashMap() static method , muy probablemente necesite burlarse de él para no crear efectos secundarios entre las clases dependientes durante las pruebas.
Y como han notado: burlarse de los métodos estáticos es realmente torpe ya que los métodos estáticos no están diseñados para ser anulados.

Además, para la lógica central del dominio, debe tener la capacidad de aprovechar el OOP (herencia, polimorfismo, patrones de diseño, etc.), ¿cómo lograrlo con métodos estáticos? -

En el caso del código heredado, no podemos cambiar, es aceptable, pero de lo contrario, no, no, y debería refactorizar su código.