2015-02-11 67 views
6

試想,我有以下類:EasyMock中的Mockito.spy/doReturn的模擬器是什麼?

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方法
  1. index.getWriteLock()被使用(不index.getReadLock()),
  2. 的取得鎖定併發布

使用我的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(行Mockito.doReturn(indexData).when(objectUnderTest).getIndex(input))?

注意:你可以找到這個例子的代碼here

+0

道歉,如果你只有w ant是與Easymock有關的確切答案,但我認爲你需要退後一步,問自己爲什麼你不得不「試探」你想要測試的課程。這通常是[認爲是代碼味道](http://programmers.stackexchange。COM /問題/ 212493/IS-偵察的測試類,壞的做法)。我認爲值得一提的是,如果您是新手撰寫這種性質的測試,並且可以選擇重構代碼。 – Brad 2015-02-13 09:40:52

+0

@Brad我知道這種做法可能被認爲是糟糕的設計。然而,對我來說,測試我想要的所有東西比擁有優雅的設計更重要。基本上,我希望能夠爲我手動檢測的大多數錯誤編寫自動化測試。在我的特殊情況下,這比純粹的設計更重要。並且代碼不能被重構。 – 2015-02-13 09:51:09

回答

4

在提供(上方,出乎我的意見)的可能解決方案的精神,你可以試試下面的

選項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(); 
    } 
} 

什麼是Mockito.spy/doReturn在了EasyMock的analogon?

所以在去除需要在你的測試間諜()中的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(); 
    } 
} 
+0

謝謝。如果您提供了EasyMock代碼示例,我會將此獎金頒發給您。我已經在其他地方看到類似於您的建議的解決方案,但它也是用Mockito編寫的,我太愚蠢了,無法將'Mockito.doReturn(lock).when(indexData).getWriteLock();'映射到EasyMock。 – 2015-02-13 11:03:08

+0

在EasyMock中使用'expect(indexData.getWriteLock())和StubReturn(lock);' – Brad 2015-02-13 11:11:27

+0

EasyMock示例添加 – Brad 2015-02-13 12:01:42

相關問題