2015-02-18 56 views
2

注意:mockito 1.10.19如何用mockito修改調用歷史記錄?

情景如下;我有一個抽象類,因爲這樣:

/** 
* 
* @param <M> metadata class 
*/ 
@ParametersAreNonnullByDefault 
public abstract class AttributeWriter<M> 
    implements AttributeWriterByName 
{ 
    protected final MetadataDriver<M> driver; 
    protected final Path path; 

    protected AttributeWriter(final Path path, final MetadataDriver<M> driver) 
    { 
     this.driver = driver; 
     this.path = path; 
    } 
} 

AttributeWriterByName界面很簡單:

@ParametersAreNonnullByDefault 
public interface AttributeWriterByName 
{ 
    void setAttributeByName(String name, Object value) 
     throws IOException; 
} 

實現的一個例子是這樣的(最簡單的存在):

@SuppressWarnings("DesignForExtension") 
@ParametersAreNonnullByDefault 
public abstract class FileOwnerAttributeWriter<M> 
    extends AttributeWriter<M> 
{ 
    protected FileOwnerAttributeWriter(final Path path, 
     final MetadataDriver<M> driver) 
    { 
     super(path, driver); 
    } 

    @Override 
    public void setAttributeByName(final String name, final Object value) 
     throws IOException 
    { 
     if (!"owner".equals(Objects.requireNonNull(name))) 
      throw new NoSuchAttributeException(name); 
     setOwner((UserPrincipal) Objects.requireNonNull(value)); 
    } 

    @SuppressWarnings("MethodMayBeStatic") 
    public void setOwner(final UserPrincipal owner) 
     throws IOException 
    { 
     throw new ReadOnlyAttributeException(); 
    } 
} 

匹配測試文件依賴於一個抽象類,其內容如下:

public abstract class AttributeWriterTest<W extends AttributeWriter<Object>> 
{ 
    protected final Path path = mock(Path.class); 
    @SuppressWarnings("unchecked") 
    protected MetadataDriver<Object> driver = mock(MetadataDriver.class); 

    protected W writer; 

    protected static FileTime nullFileTime() 
    { 
     return isNull(FileTime.class); 
    } 

    @BeforeMethod 
    public abstract void init() 
     throws IOException; 
} 

至於實際的測試類,它是:

public final class FileOwnerAttributeWriterTest 
    extends AttributeWriterTest<FileOwnerAttributeWriter<Object>> 
{ 
    @BeforeMethod 
    @Override 
    public void init() 
     throws IOException 
    { 
     writer = spy(new FileOwnerAttributeWriter<Object>(path, driver) 
     { 
     }); 

     doNothing().when(writer).setOwner(any(UserPrincipal.class)); 
    } 

    @Test 
    public void setOwnerTest() 
     throws IOException 
    { 
     final UserPrincipal owner = mock(UserPrincipal.class); 

     writer.setAttributeByName("owner", owner); 

     verify(writer).setOwner(same(owner)); 
    } 
} 

現在,我的問題是:我基本上是要檢查的.setAttributeName()調用後,沒有什麼事情發生其他.setOwner()

但是,如果我添加到測試,我想verifyNoMoreInteractions(writer),這會因爲在這種相同的測試。我祈求.setAttributeByName()失敗...

儘管事實上,這是不是有可能是與我的設計問題更多(我仍在試驗),是否有辦法告訴mockito在這樣的測試中忽略了對setAttributeByName()的調用,以便我可以寫這個?

verify(writer, only()).setOwner(same(owner)); 

編輯我想什麼能寫,或者如果它已經存在了相當的,是這樣的:

@Test 
public void setOwnerTest() 
    throws IOException 
{ 
    final UserPrincipal owner = mock(UserPrincipal.class); 

    ignoreInvocation(writer).setAttributeByName("owner", owner); 

    verify(writer, only()).setOwner(same(owner)); 
} 
+0

難道你不能在驗證呼叫後調用verifyNoMoreInteractions(writer)*嗎? setOwner調用後沒有任何調用。 – 2015-02-18 01:24:03

+0

@CarlManaster雖然這聽起來像是要做的事情,但問題是,模擬也會記錄對'.setAttributeByName()'的調用...因此,這是行不通的:/ – fge 2015-02-18 01:31:38

+0

好吧,如果您希望調用'setOwner()'和'setAttributeByName()',那麼這不應該是你驗證? – 2015-02-18 01:33:19

回答

0

我發現了一個辦法做到這一點,看到我下面的簡單例子。總之,您在觸發真實方法調用之前重置模擬。

我回答這是一個練習擺弄Mockito的練習,但我希望你明顯幾乎肯定不應該這樣做。

public class SimplifiedExample { 

    class ClassUnderTest { 
    public void doSomething(String value) { 
     doSomethingElse(value); 
    } 

    public void doSomethingElse(String value) { 
     System.out.println(value); 
    } 
    } 

    @Test 
    public void testMethod() throws Exception { 
    ClassUnderTest foo = spy(new ClassUnderTest());  
    final String input = "bar"; 

    doAnswer(new Answer<Void>() { 
     @Override 
     public Void answer(InvocationOnMock invocation) throws Throwable { 
     reset(foo); 
     invocation.callRealMethod(); 
     return null; 
     } 
    }).when(foo).doSomething(anyString()); 

    foo.doSomething(input); 
    verify(foo, only()).doSomethingElse(input); 
    } 
} 
+0

「我希望你很明顯幾乎肯定不應該這樣做。」 < - 是的,我知道這是一個設計錯誤... – fge 2015-02-18 17:07:46