2015-02-11 5 views
6

Stellen Sie sich vor, ich habe folgende Klasse:Was ist das Analogon von Mockito.spy/doReturn in EasyMock?

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; 
    } 
} 

Ich möchte ein Unit-Test, der die

  1. im add Verfahren, index.getWriteLock() verwendet wird (nicht index.getReadLock()),
  2. die prüft schreiben Schloss ist genommen und
  3. freigegeben.

Mit Mockito ich einen Test wie folgt schreiben kann:

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

Wie kann ich die gleiche Sache mit EasyMock tun?

Beton: Wie kann ich die getIndex Methode einen Schein in EasyMock (Zeile Mockito.doReturn(indexData).when(objectUnderTest).getIndex(input)) zurückgeben?

Hinweis: Sie finden den Code dieses Beispiels here.

+0

Entschuldigung, wenn Sie nur w und eine genaue Antwort zu Easymock, aber ich denke, du musst einen Schritt zurück machen und dich fragen, warum du die Klasse, die du zu testen versuchst (Spionage). Dies ist in der Regel ein Code-Geruch (http: //programmers.stackexchange).com/questions/212493/is-spying-on-getestete-Klasse-bad-Praxis). Ich dachte, es wäre erwähnenswert, wenn Sie neue Tests schreiben und den Code umgestalten können. – Brad

+0

@Brad Ich weiß, dass diese Praxis als ein schlechtes Design angesehen werden kann. Für mich ist es jedoch wichtiger, alles zu testen, als ein elegantes Design zu haben. Grundsätzlich möchte ich einen automatisierten Test für die meisten Fehler, die ich manuell erkenne, schreiben können. In meiner speziellen Situation ist das einfach wichtiger als schönes Design. Und der Code kann nicht refaktoriert werden. –

Antwort

4

Im Geiste eine mögliche Lösung bereitzustellen (und im Gegensatz zu meinen Kommentaren oben) können Sie eine der folgenden

Option

Wenn TestClass implementiert eine Schnittstelle 1 könnten versuchen Sie einen ähnlichen Test erreichen könnte mit andDelegateTo() wie in diesem Beitrag beschrieben, die über Easymock not supporting spying

Option 2

spricht

Machen Sie Ihre Spionage überflüssig, indem Sie die TestClass speziell für Ihre Testanforderungen erweitern. Dies ist ein gängiger Ansatz für den Umgang mit älteren Codebasen, bei denen Sie den zu testenden Code nicht ändern können.

Ich werde Mockito in diesem Beispiel verwenden, so dass es mit Ihrer Frage ausgerichtet ist, aber das Konzept wird das gleiche mit Easymock funktionieren.

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

Was ist das Analogon von Mockito.spy/doReturn in EasyMock?

So die Notwendigkeit eines Spy entfernt haben() in Ihren Tests rufen die Mockito

Mockito.doReturn(lock).when(indexData).getWriteLock(); 

Kann oben in EasyMock als

expect(indexData.getWriteLock()).andStubReturn(lock); 

EasyMock Beispiel derselben Mockito Test geschrieben werden

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

Danke. Ich werde Ihnen diese Prämie gewähren, wenn Sie ein EasyMock-Beispiel für den Code bereitstellen. Ich habe schon anderswo eine Lösung gesehen, die der von Ihnen vorgeschlagenen ähnlich ist, aber es wurde auch in Mockito geschrieben und ich bin zu dumm, um 'Mockito.doReturn (lock) .when (indexData) .getWriteLock();' auf EasyMock abzubilden. –

+0

In EasyMock verwenden 'expect (indexData.getWriteLock()) .undStubReturn (lock);' – Brad

+0

EasyMock-Beispiel hinzugefügt – Brad