想象一下,我有以下课程:
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做同样的事情?
具体:我怎样才能使getIndex方法在EasyMock中返回一个模拟(行Mockito.doReturn(indexData).when(objectUnderTest).getIndex(input))?
解决方法
本着提供可能解决方案的精神(与我上面的评论相反),您可以尝试以下方法之一
选项1
如果TestClass实现了一个接口,你可以使用andDelegateTo()进行类似的测试,如本文所述,讨论的是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(); } }
EasyMock中Mockito.spy / doReturn的类比是什么?
因此,在您的测试中删除了对Mockito调用的Spy()的需求
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(); } }