EasyMock 中 Mockito.spy/doReturn 的类比是什么?
What is the analogon of Mockito.spy/doReturn in EasyMock?
想象一下,我有以下 class:
public class TestClass {
public class Index<X> {
}
public class IndexData {
private final Index<?> index;
private final ReentrantReadWriteLock lock =
new ReentrantReadWriteLock();
public IndexData(final Index<?> index) {
super();
this.index = index;
}
public Index<?> getIndex() {
return index;
}
public Lock getReadLock() {
return lock.readLock();
}
public Lock getWriteLock() {
return lock.writeLock();
}
}
public void add(final InputClass input)
{
final IndexData index = getIndex(input);
final Lock lock = index.getWriteLock();
lock.lock();
try {
// Do something here, which requires synchronization
} finally {
lock.unlock();
}
}
protected IndexData getIndex(final InputClass input) {
// Some logic of getting the index for input
return null;
}
}
我想写一个单元测试来验证
- 在
add
方法中,使用了index.getWriteLock()
(不是index.getReadLock()
),
- 锁被占用并且
- 已发布。
使用 Mockito 我可以编写这样的测试:
@Test
public void testAddUsesWriteLock() {
// Prepare
final TestClass objectUnderTest = Mockito.spy(new TestClass());
final InputClass input = Mockito.mock(InputClass.class);
final IndexData indexData = Mockito.mock(IndexData.class);
Mockito.doReturn(indexData).when(objectUnderTest).getIndex(input);
final Lock lock = Mockito.mock(Lock.class);
Mockito.doReturn(lock).when(indexData).getWriteLock();
// Invoke method under test
objectUnderTest.add(input);
// Verify
Mockito.verify(indexData).getWriteLock();
Mockito.verify(indexData, Mockito.never()).getReadLock();
Mockito.verify(lock).lock();
Mockito.verify(lock).unlock();
}
如何使用 EasyMock 做同样的事情?
具体:如何在 EasyMock 中模拟 getIndex
方法 return(第 Mockito.doReturn(indexData).when(objectUnderTest).getIndex(input)
行)?
注意:你可以找到这个例子的代码here。
本着提供可能解决方案的精神(与我上面的评论相反),您可以尝试以下方法之一
选项 1
如果 TestClass
实现了一个接口,您可以使用 andDelegateTo() as described in this post that talks about Easymock not supporting spying
实现类似的测试
选项 2
通过专门针对您的测试要求扩展 TestClass
来消除您对间谍的需求。这是处理无法更改被测代码的遗留代码库的常用方法。
我将在这个示例中使用 Mockito,以便它与您的问题保持一致,但是这个概念将与 Easymock 相同。
public class TestClassUsingMockito {
/**
We extend the original class under test so that we can override the creation of IndexData and
thereby remove the responsibility of creating this object from the @Test method
*/
private class ClassForTesting extends TestClass {
private Lock lock;
private IndexData indexData;
public ClassForTesting(IndexData indexData, Lock lock) {
this.indexData = indexData;
this.lock = lock;
}
@Override
protected IndexData getIndex(InputClass input) {
return indexData;
}
}
/**
Look Ma' no more Spys!
*/
@Test
public void testAddUsesWriteLock() {
// Prepare
final Lock lock = Mockito.mock(Lock.class);
final IndexData indexData = Mockito.mock(IndexData.class);
Mockito.doReturn(lock).when(indexData).getWriteLock();
// ... now use your new subclass for testing
final TestClass objectUnderTest = new ClassForTesting(indexData, lock);
final InputClass input = Mockito.mock(InputClass.class);
// Invoke method under test
objectUnderTest.add(input);
// Verify
Mockito.verify(indexData).getWriteLock();
Mockito.verify(indexData, Mockito.never()).getReadLock();
Mockito.verify(lock).lock();
Mockito.verify(lock).unlock();
}
}
Mockito.spy/doReturn在EasyMock中的类比是什么?
因此,在您的测试中消除了对 Spy() 的需求后,Mockito 调用
Mockito.doReturn(lock).when(indexData).getWriteLock();
在EasyMock中可以写成
expect(indexData.getWriteLock()).andStubReturn(lock);
上面相同 Mockito 测试的 EasyMock 示例
public class TestClassUsingEasymock extends EasyMockSupport {
private class ClassForTesting extends TestClass {
private Lock lock;
private IndexData indexData;
public ClassForTesting(IndexData indexData, Lock lock) {
this.indexData = indexData;
this.lock = lock;
}
@Override
protected IndexData getIndex(InputClass input) {
return indexData;
}
}
@Test
public void testAddUsesWriteLock() {
// Prepare
final Lock lock = createNiceMock(Lock.class);
final IndexData indexData = createNiceMock(IndexData.class);
EasyMock.expect(indexData.getWriteLock()).andStubReturn(lock);
// ... now use your new subclass for testing
final TestClass objectUnderTest = new ClassForTesting(indexData, lock);
final InputClass input = createNiceMock(InputClass.class);
lock.lock();
EasyMock.expectLastCall();
lock.unlock();
EasyMock.expectLastCall();
replayAll();
// Invoke method under test
objectUnderTest.add(input);
// Verify
verifyAll();
}
}
想象一下,我有以下 class:
public class TestClass {
public class Index<X> {
}
public class IndexData {
private final Index<?> index;
private final ReentrantReadWriteLock lock =
new ReentrantReadWriteLock();
public IndexData(final Index<?> index) {
super();
this.index = index;
}
public Index<?> getIndex() {
return index;
}
public Lock getReadLock() {
return lock.readLock();
}
public Lock getWriteLock() {
return lock.writeLock();
}
}
public void add(final InputClass input)
{
final IndexData index = getIndex(input);
final Lock lock = index.getWriteLock();
lock.lock();
try {
// Do something here, which requires synchronization
} finally {
lock.unlock();
}
}
protected IndexData getIndex(final InputClass input) {
// Some logic of getting the index for input
return null;
}
}
我想写一个单元测试来验证
- 在
add
方法中,使用了index.getWriteLock()
(不是index.getReadLock()
), - 锁被占用并且
- 已发布。
使用 Mockito 我可以编写这样的测试:
@Test
public void testAddUsesWriteLock() {
// Prepare
final TestClass objectUnderTest = Mockito.spy(new TestClass());
final InputClass input = Mockito.mock(InputClass.class);
final IndexData indexData = Mockito.mock(IndexData.class);
Mockito.doReturn(indexData).when(objectUnderTest).getIndex(input);
final Lock lock = Mockito.mock(Lock.class);
Mockito.doReturn(lock).when(indexData).getWriteLock();
// Invoke method under test
objectUnderTest.add(input);
// Verify
Mockito.verify(indexData).getWriteLock();
Mockito.verify(indexData, Mockito.never()).getReadLock();
Mockito.verify(lock).lock();
Mockito.verify(lock).unlock();
}
如何使用 EasyMock 做同样的事情?
具体:如何在 EasyMock 中模拟 getIndex
方法 return(第 Mockito.doReturn(indexData).when(objectUnderTest).getIndex(input)
行)?
注意:你可以找到这个例子的代码here。
本着提供可能解决方案的精神(与我上面的评论相反),您可以尝试以下方法之一
选项 1
如果 TestClass
实现了一个接口,您可以使用 andDelegateTo() as described in this post that talks about Easymock not supporting spying
选项 2
通过专门针对您的测试要求扩展 TestClass
来消除您对间谍的需求。这是处理无法更改被测代码的遗留代码库的常用方法。
我将在这个示例中使用 Mockito,以便它与您的问题保持一致,但是这个概念将与 Easymock 相同。
public class TestClassUsingMockito {
/**
We extend the original class under test so that we can override the creation of IndexData and
thereby remove the responsibility of creating this object from the @Test method
*/
private class ClassForTesting extends TestClass {
private Lock lock;
private IndexData indexData;
public ClassForTesting(IndexData indexData, Lock lock) {
this.indexData = indexData;
this.lock = lock;
}
@Override
protected IndexData getIndex(InputClass input) {
return indexData;
}
}
/**
Look Ma' no more Spys!
*/
@Test
public void testAddUsesWriteLock() {
// Prepare
final Lock lock = Mockito.mock(Lock.class);
final IndexData indexData = Mockito.mock(IndexData.class);
Mockito.doReturn(lock).when(indexData).getWriteLock();
// ... now use your new subclass for testing
final TestClass objectUnderTest = new ClassForTesting(indexData, lock);
final InputClass input = Mockito.mock(InputClass.class);
// Invoke method under test
objectUnderTest.add(input);
// Verify
Mockito.verify(indexData).getWriteLock();
Mockito.verify(indexData, Mockito.never()).getReadLock();
Mockito.verify(lock).lock();
Mockito.verify(lock).unlock();
}
}
Mockito.spy/doReturn在EasyMock中的类比是什么?
因此,在您的测试中消除了对 Spy() 的需求后,Mockito 调用
Mockito.doReturn(lock).when(indexData).getWriteLock();
在EasyMock中可以写成
expect(indexData.getWriteLock()).andStubReturn(lock);
上面相同 Mockito 测试的 EasyMock 示例
public class TestClassUsingEasymock extends EasyMockSupport {
private class ClassForTesting extends TestClass {
private Lock lock;
private IndexData indexData;
public ClassForTesting(IndexData indexData, Lock lock) {
this.indexData = indexData;
this.lock = lock;
}
@Override
protected IndexData getIndex(InputClass input) {
return indexData;
}
}
@Test
public void testAddUsesWriteLock() {
// Prepare
final Lock lock = createNiceMock(Lock.class);
final IndexData indexData = createNiceMock(IndexData.class);
EasyMock.expect(indexData.getWriteLock()).andStubReturn(lock);
// ... now use your new subclass for testing
final TestClass objectUnderTest = new ClassForTesting(indexData, lock);
final InputClass input = createNiceMock(InputClass.class);
lock.lock();
EasyMock.expectLastCall();
lock.unlock();
EasyMock.expectLastCall();
replayAll();
// Invoke method under test
objectUnderTest.add(input);
// Verify
verifyAll();
}
}