usa una que puede poo para otra interfaz herencia heredar funcion definicion clases clase animal abstractas abstracta java mocking mockito

puede - para que se usa una clase abstracta en java



Usa Mockito para burlarte de algunos métodos pero no de otros. (5)

La burla parcial de una clase también es compatible a través de Spy en mockito

List list = new LinkedList(); List spy = spy(list); //optionally, you can stub out some methods: when(spy.size()).thenReturn(100); //using the spy calls real methods spy.add("one"); spy.add("two"); //size() method was stubbed - 100 is printed System.out.println(spy.size());

Verifique los documentos 1.10.19 y 2.7.22 para una explicación detallada.

¿Hay alguna manera, usando Mockito, para burlarse de algunos métodos en una clase, pero no de otros?

Por ejemplo, en esta clase de Stock (admitida), quiero simular los valores devueltos getPrice () y getQuantity () (como se muestra en el fragmento de prueba a continuación) pero quiero que getValue () realice la multiplicación como se codificó en el Stock clase

public class Stock { private final double price; private final int quantity; Stock(double price, int quantity) { this.price = price; this.quantity = quantity; } public double getPrice() { return price; } public int getQuantity() { return quantity; } public double getValue() { return getPrice() * getQuantity(); } @Test public void getValueTest() { Stock stock = mock(Stock.class); when(stock.getPrice()).thenReturn(100.00); when(stock.getQuantity()).thenReturn(200); double value = stock.getValue(); // Unfortunately the following assert fails, because the mock Stock getValue() method does not perform the Stock.getValue() calculation code. assertEquals("Stock value not correct", 100.00*200, value, .00001); }


La burla parcial usando el método de espía de Mockito podría ser la solución a su problema, como ya se indicó en las respuestas anteriores. Hasta cierto punto, estoy de acuerdo en que, para su caso de uso concreto, puede ser más apropiado burlarse de la búsqueda de DB. Desde mi experiencia, esto no siempre es posible, al menos no sin otras soluciones, que consideraría muy engorrosas o al menos frágiles. Tenga en cuenta que la burla parcial no funciona con las versiones aliadas de Mockito. Tienes uso al menos 1.8.0.

Habría escrito un comentario simple para la pregunta original en lugar de publicar esta respuesta, pero no lo permite.

Solo una cosa más: realmente no puedo entender que muchas veces se hace una pregunta aquí, se comenta con "Por qué quieres hacer esto" sin al menos intentar entender el problema. Especialmente cuando se trata de la necesidad de una burla parcial, hay muchos casos de uso que puedo imaginar en los que sería útil. Es por eso que los chicos de Mockito proporcionaron esa funcionalidad. Esta característica, por supuesto, no debe ser usada en exceso. Pero cuando hablamos de configuraciones de casos de prueba que de otra manera no podrían establecerse de una manera muy complicada, se debe usar el espionaje.


La respuesta aceptada no es correcta de acuerdo con la pregunta.

La llamada a Stock stock = mock(Stock.class); llama a org.mockito.Mockito.mock(Class<T>) que se ve así:

public static <T> T mock(Class<T> classToMock) { return mock(classToMock, withSettings().defaultAnswer(RETURNS_DEFAULTS)); }

Los documentos del valor RETURNS_DEFAULTS indican:

/** * The default <code>Answer</code> of every mock <b>if</b> the mock was not stubbed. * Typically it just returns some empty value. * <p> * {@link Answer} can be used to define the return values of unstubbed invocations. * <p> * This implementation first tries the global configuration. * If there is no global configuration then it uses {@link ReturnsEmptyValues} (returns zeros, empty collections, nulls, etc.) */

Lo que quieres es org.mockito.Mockito.CALLS_REAL_METHODS acuerdo con la documentación:

/** * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)} * <p> * {@link Answer} can be used to define the return values of unstubbed invocations. * <p> * This implementation can be helpful when working with legacy code. * When this implementation is used, unstubbed methods will delegate to the real implementation. * This is a way to create a partial mock object that calls real methods by default. * <p> * As usual you are going to read <b>the partial mock warning</b>: * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects. * How does partial mock fit into this paradigm? Well, it just doesn''t... * Partial mock usually means that the complexity has been moved to a different method on the same object. * In most cases, this is not the way you want to design your application. * <p> * However, there are rare cases when partial mocks come handy: * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.) * However, I wouldn''t use partial mocks for new, test-driven & well-designed code. * <p> * Example: * <pre class="code"><code class="java"> * Foo mock = mock(Foo.class, CALLS_REAL_METHODS); * * // this calls the real implementation of Foo.getSomething() * value = mock.getSomething(); * * when(mock.getSomething()).thenReturn(fakeValue); * * // now fakeValue is returned * value = mock.getSomething(); * </code></pre> */

Por lo tanto, su código debe verse como:

import org.junit.Test; import static org.mockito.Mockito.*; import static org.junit.Assert.*; public class StockTest { public class Stock { private final double price; private final int quantity; Stock(double price, int quantity) { this.price = price; this.quantity = quantity; } public double getPrice() { return price; } public int getQuantity() { return quantity; } public double getValue() { return getPrice() * getQuantity(); } } @Test public void getValueTest() { Stock stock = mock(Stock.class, withSettings().defaultAnswer(CALLS_REAL_METHODS)); when(stock.getPrice()).thenReturn(100.00); when(stock.getQuantity()).thenReturn(200); double value = stock.getValue(); assertEquals("Stock value not correct", 100.00 * 200, value, .00001); } }


Para responder directamente a tu pregunta, sí, puedes burlarte de algunos métodos sin burlarte de otros. Esto se llama un simulacro parcial . Consulte la documentación de Mockito sobre simulacros parciales para obtener más información.

Para su ejemplo, puede hacer algo como lo siguiente, en su prueba:

Stock stock = mock(Stock.class); when(stock.getPrice()).thenReturn(100.00); // Mock implementation when(stock.getQuantity()).thenReturn(200); // Mock implementation when(stock.getValue()).thenCallRealMethod(); // Real implementation

En ese caso, cada implementación del método se thenCallRealMethod() , a menos que especifique thenCallRealMethod() en la cláusula when(..) .

También hay una posibilidad al revés con espías en lugar de simulacros :

Stock stock = spy(Stock.class); when(stock.getPrice()).thenReturn(100.00); // Mock implementation when(stock.getQuantity()).thenReturn(200); // Mock implementation // All other method call will use the real implementations

En ese caso, todas las implementaciones de métodos son las reales, excepto si ha definido un comportamiento simulado con when(..) .

Hay un error importante cuando se usa when(Object) con espía como en el ejemplo anterior. Se llamará al método real (porque stock.getPrice() se evalúa antes de when(..) en tiempo de ejecución). Esto puede ser un problema si su método contiene una lógica que no debería llamarse. Puedes escribir el ejemplo anterior así:

Stock stock = spy(Stock.class); doReturn(100.00).when(stock).getPrice(); // Mock implementation doReturn(200).when(stock).getQuantity(); // Mock implementation // All other method call will use the real implementations

Sin embargo, con su ejemplo, creo que aún fallará, ya que la implementación de getValue() basa en la quantity y el price , en lugar de getQuantity() y getPrice() , que es lo que se ha burlado.

Lo que realmente parece que quieres es solo:

@Test public void getValueTest() { Stock stock = new Stock(100.00, 200); double value = stock.getValue(); assertEquals("Stock value not correct", 100.00*200, value, .00001); }


Según los docs :

Foo mock = mock(Foo.class, CALLS_REAL_METHODS); // this calls the real implementation of Foo.getSomething() value = mock.getSomething(); when(mock.getSomething()).thenReturn(fakeValue); // now fakeValue is returned value = mock.getSomething();