2015-02-11 65 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

相关问题