Burlándose de una conexión de URL utilizando PowerMockito
Estoy tratando de probar mi código que analiza una respuesta JSON de una URL.
Este es el código que estoy tratando de probar:
public String getJsonResponseFromUrl(String url) {
JSONObject jsonObject = null;
try {
URL apiUrl = new URL(url);
jsonObject = new JSONObject(IOUtils.toString(apiUrl, StandardCharsets.UTF_8));
} catch (IOException e) {
System.out.println(e);
}
return jsonObject.toString();
}
Este es el test Junit que he configurado:
import java.net.URL;
import org.json.JSONObject;
@RunWith(MockitoJUnitRunner.class)
@PrepareForTest({URL.class, Service.class, JSONObject.class})
public class ServiceTest {
private JSONObject mockJsonObject;
private URL mockUrl;
@InjectMocks
private Service mockService;
@Before
public void setUp() throws Exception {
mockJsonObject = PowerMockito.mock(JSONObject.class);
mockUrl = PowerMockito.mock(URL.class);
}
@Test
public void testGetJsonResponseFromUrl() throws Exception {
String url = "http://some-url.com";
PowerMockito.whenNew(URL.class).withArguments(url).thenReturn(mockUrl);
PowerMockito.whenNew(JSONObject.class).withAnyArguments().thenReturn(mockJsonObject);
mockService.getJsonResponseFromUrl(url);
}
}
El problema ocurre con el objeto URL simulado.
mockUrl = PowerMockito.mock(URL.class);
Cuando el método setUp llega a esa línea, obtengo este error en la consola:
java.lang.RuntimeException: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @593634ad
Según entiendo, PowerMockito permite simular clases finales como la clase URL.
No sé si hay algo que me estoy pasando por alto.
Versión de PowerMockito: 2.0.9
Versión de Junit: 4.12
Gracias.
EDITAR: Me doy cuenta de que la prueba en esta clase realmente no está probando nada (es decir, no hay afirmaciones). Hice esta prueba para verificar primero que todo se estuviera simulando correctamente.
davy.ai
Solución para probar el código que analiza una respuesta JSON de una URL
Problema
Estoy intentando probar el siguiente código que analiza una respuesta JSON de una URL, pero me estoy encontrando con un error con el objeto URL simulado:
Solución
Para simular el objeto URL, necesitas usar
PowerMockito.whenNew()
para interceptar la llamada al constructor de URL y devolver el objeto simulado en su lugar. Sin embargo, necesitas preparar la clase para simularla estáticamente, así como también la clase Service y la clase JSONObject. Esto se puede hacer con la anotación@PrepareForTest
:En el ejemplo anterior, usamos
whenNew(URL.class)
para crear una interceptación que devuelve el objeto simulado cuando se llama al constructor de URL con la URL especificada. Luego, usamoswhenNew(JSONObject.class)
para crear una interceptación que devuelve el objeto simulado cada vez que se llama al constructor de JSONObject con cualquier argumento de cadena. Finalmente, llamamos al métodoservice.getJsonResponseFromUrl(url)
y comprobamos que el resultado sea el mismo que el JSONObject simulado.Además, para activar el método simulado
getJsonResponseFromUrl()
, usamosservice = spy(new Service());
ya que@InjectMocks
no es necesario aquí.Espero que esta solución ayude a resolver tu problema.