Vic*_*azi 354 java mocking mockito
有没有办法,使用Mockito来模拟一个类中的某些方法,而不是其他方法?
例如,在这个(公认的设计)Stock类中我想模拟getPrice()和getQuantity()返回值(如下面的测试片段所示),但我希望getValue()执行在Stock中编码的乘法类
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);
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*uis 558
要直接回答你的问题,是的,你可以模拟一些方法而不会嘲笑其他方法.这称为部分模拟.有关详细信息,请参阅有关部分模拟的Mockito文档.
对于您的示例,您可以在测试中执行以下操作:
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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,除非thenCallRealMethod()在when(..)子句中指定,否则将模拟每个方法实现.
还有一种可能性与间谍相反而不是模拟:
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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,除非您已使用定义了模拟行为,否则所有方法实现都是真实的when(..).
when(Object)与前一个例子中一样使用间谍时,有一个重要的陷阱.将调用真实方法(因为在运行stock.getPrice()之前进行评估when(..)).如果您的方法包含不应调用的逻辑,则可能会出现问题.您可以像这样编写上一个示例:
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
Run Code Online (Sandbox Code Playgroud)
然而,随着你的榜样,我相信它仍然会失败,因为实施org.mockito.Mockito.CALLS_REAL_METHODS依赖于getValue()和quantity,而不是price和getQuantity(),这是你嘲笑什么.
你真正想要的只是:
Stock MOCK_STOCK = Mockito.mock( Stock.class, CALLS_REAL_METHODS );
Run Code Online (Sandbox Code Playgroud)
Sud*_*han 129
在mockito中也可以通过Spy支持对类的部分模拟
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());
Run Code Online (Sandbox Code Playgroud)
ema*_*ema 33
根据文件:
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();
Run Code Online (Sandbox Code Playgroud)
the*_*ude 17
根据问题,接受的答案是不正确的.
要将呼叫org.mockito.Mockito.CALLS_REAL_METHODS通话Stock stock = mock(Stock.class);,看起来像这样:
/**
* 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>
*/
Run Code Online (Sandbox Code Playgroud)
值的文档org.mockito.Mockito.mock(Class<T>)告诉:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
你想要的是RETURNS_DEFAULTS根据文档:
public static <T> T mock(Class<T> classToMock) {
return mock(classToMock, withSettings().defaultAnswer(RETURNS_DEFAULTS));
}
Run Code Online (Sandbox Code Playgroud)
因此,您的代码应如下所示:
/**
* 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.)
*/
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
363235 次 |
| 最近记录: |