2010-04-19 19 views
28

public Object doSomething(Object o);我想嘲笑。它應該只返回它的參數。我想:我該如何模擬easymock中的一個方法,該方法將返回其參數之一?

Capture<Object> copyCaptcher = new Capture<Object>(); 
expect(mock.doSomething(capture(copyCaptcher))) 
     .andReturn(copyCatcher.getValue()); 

但沒有成功,我得到的只是一個AssertionError作爲java.lang.AssertionError: Nothing captured yet。有任何想法嗎?

回答

18

我一直在尋找同樣的行爲,最後寫道:

 
import org.easymock.EasyMock; 
import org.easymock.IAnswer; 

/** 
* Enable a Captured argument to be answered to an Expectation. 
* For example, the Factory interface defines the following 
* <pre> 
* CharSequence encode(final CharSequence data); 
* </pre> 
* For test purpose, we don't need to implement this method, thus it should be mocked. 
* <pre> 
* final Factory factory = mocks.createMock("factory", Factory.class); 
* final ArgumentAnswer<CharSequence> parrot = new ArgumentAnswer<CharSequence>(); 
* EasyMock.expect(factory.encode(EasyMock.capture(new Capture<CharSequence>()))).andAnswer(parrot).anyTimes(); 
* </pre> 
* Created on 22 juin 2010. 
* @author Remi Fouilloux 
* 
*/ 
public class ArgumentAnswer<T> implements IAnswer<T> { 

    private final int argumentOffset; 

    public ArgumentAnswer() { 
     this(0); 
    } 

    public ArgumentAnswer(int offset) { 
     this.argumentOffset = offset; 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    @SuppressWarnings("unchecked") 
    public T answer() throws Throwable { 
     final Object[] args = EasyMock.getCurrentArguments(); 
     if (args.length < (argumentOffset + 1)) { 
      throw new IllegalArgumentException("There is no argument at offset " + argumentOffset); 
     } 
     return (T) args[argumentOffset]; 
    } 

} 

我寫了一個快速的「如何」中的類的javadoc。

希望這會有所幫助。

+0

謝謝!雖然我改變了原來的單元測試,但我相信我會再次遇到這個問題! (您可能想將其提供給EM direclty?) – Jan 2010-06-24 16:27:59

+3

Capture是您的javadoc示例中的一個紅色鯡魚 - 它不是必需的:EasyMock.expect(factory.encode(anyObject()))。andAnswer(parrot).anyTimes(); – thetoolman 2012-01-17 20:09:05

2

嗯,如果我正確理解你的問題,我想你可能會過於複雜化。

Object someObject = .... ;
expect(mock.doSomething(someObject)).andReturn(someObject);

應該只是罰款。請記住,您提供了期望的參數和返回值。因此在兩部作品中使用相同的對象。

+0

我不不知道「someObject」。它在我想測試的方法中被實例化。考慮一個內部調用「圖像過濾器(圖像圖像)」(模擬)的方法「createImage(InputStream image)」(剪切)。 – Jan 2010-04-24 11:39:45

+0

啊。好。然後你可以做幾件事情。首先,您可以使用isA()參數匹配器來測試該對象是一個特定的類。其次,我會建議編寫自己的參數捕獲。我沒有這樣做,但我寫了自己的參數匹配器。例如,如果您想檢查bean屬性,那麼這非常有用。不幸的是,我沒有這個代碼,但是如果你看一下編寫匹配器的例子,這並不難。 – drekka 2010-04-26 04:00:02

+0

你的代碼是有效的,但它沒有回答使用其中一個參數的問題 - 它使用的是已知對象。 – thetoolman 2012-01-13 01:47:22

22

那麼,最簡​​單的方法就是在IAnswer實現中使用Capture ...當做這個內聯時,你必須聲明它當然是final

MyService mock = createMock(MyService.class); 

final Capture<ParamAndReturnType> myCapture = new Capture<ParamAndReturnType>(); 
expect(mock.someMethod(capture(myCapture))).andAnswer(
    new IAnswer<ParamAndReturnType>() { 
     @Override 
     public ParamAndReturnType answer() throws Throwable { 
      return myCapture.getValue(); 
     } 
    } 
); 
replay(mock) 

這可能是最準確的方法,不依賴於某些上下文信息。這對我來說每次都是這樣。

+0

我更喜歡Remi Fouilloux的帖子並經常使用它。它消除了對catpure對象的需求。 – Jan 2011-10-26 15:39:53

+0

很好的回答。使用Java 8 lambda,整個IAnswer匿名子類可以重寫爲「myCapture :: getValue」。 – 2017-02-16 13:47:07

12

捕獲是用於測試傳遞給模擬後的值。如果你只需要一個模擬來返回一個參數(或者從參數計算出來的某個值),你只需要實現IAnswer。

請參閱「雷米Fouilloux」的實現,如果你想通過放慢參數X背部的可重複使用的方式,但忽略例如他利用捕獲的。

如果你只是想像「do_the_trick」的例子那樣內聯它,那麼捕獲在這裏就是一個紅鯡魚。下面是簡化版本:

MyService mock = createMock(MyService.class); 
expect(mock.someMethod(anyObject(), anyObject()).andAnswer(
    new IAnswer<ReturnType>() { 
     @Override 
     public ReturnType answer() throws Throwable { 
      // you could do work here to return something different if you needed. 
      return (ReturnType) EasyMock.getCurrentArguments()[0]; 
     } 
    } 
); 
replay(mock) 
+0

與我的首選答案相同,對嗎? – Jan 2012-01-18 20:29:01

+0

不是,我的觀點是在「Remi Fouilloux」的代碼中,Capture javadoc示例是不需要的。這也是「do_the_trick」示例代碼中不需要的,如上所述。 – thetoolman 2012-02-16 21:06:36

7

基於@does_the_trick和使用lambda表達式,你現在可以寫:

MyService mock = EasyMock.createMock(MyService.class); 

final Capture<ParamAndReturnType> myCapture = EasyMock.newCapture(); 
expect(mock.someMethod(capture(myCapture))).andAnswer(() -> myCapture.getValue()); 

或不捕捉爲@thetoolman建議

expect(mock.someMethod(capture(myCapture))) 
.andAnswer(() -> (ParamAndReturnType)EasyMock.getCurrentArguments()[0]); 
相關問題