簡體   English   中英

Mockito間諜方法不起作用

[英]Mockito spy method not working

我遇到了mockito.spy方法的問題。

我最近到了一個“舊”項目,我的第一個任務是在其中添加mockito,並進行真正的單元測試:)

該項目存在許多概念問題,但這不是重點;)

我解釋一下我的問題:

我上課了

public class Tutu{
  public Tutu(){
  }
}

public class Toto{
  public Toto(){
  }
  public int executeToto(Tutu tutu){
    //do some stuff
    return 5;
  }
}

public class Titi{
  private Toto toto;

  public Titi(){
     this.toto = new Toto();     
  }

  public void executeTiti(){
      //do some stuff
      Tutu tutu = new Tutu();
      int ret = this.toto.executeToto(tutu);
      //do some stuff
  }
}

在我的測試類TitiTest.java中我想只測試executeTiti,我不想測試executeToto的東西,因為這個類有自己的測試類TotoTest.java。

但正如你所看到的,toto是在titi構造函數中實例化的,所以我嘗試這樣的事情:(我也在我的測試中使用PowerMock,所以我使用的是PowerMockRunner,但它似乎不是問題)

@RunWith(PowerMockRunner.class)
public class TitiTest {

 @Test
 public void testExecuteTiti(){
   Toto toto = Mockito.spy(new Toto());
   Mockito.doReturn(2).when(toto).executeToto(Mockito.any(Tutu.class));

   Titi testedObject = new Titi();
   testedObject.executeTiti();
 }
}

但真正的方法是每次調用和ret = 5 :(

我錯過了什么嗎? 我在stackoverflow上閱讀了很多關於這個的帖子並嘗試了所有解決方案,但它永遠不會工作,因為我認為我做對了。

我使用junit4.11 / powermock1.5.4 / mockito1.9.5

Toto toto = Mockito.spy(new Toto());

請記住,您在此行中創建的Toto實例上的間諜/存根,而不是每個新創建的Toto。 所以當你打電話時:

Titi testedObject = new Titi();
testedObject.executeTiti();

構造函數new Titi()本身創建了一個不受Mockito影響的Toto新實例,因此對this.toto.executeAction()調用將始終返回5。


因為您正在使用PowerMockito運行,所以您可以選擇對Toto的構造函數進行存根

@RunWith(PowerMockRunner.class)
@PrepareForTest(Titi.class) // stub the calling class Titi, not Toto!
public class TitiTest {
  @Test public void testExecuteTiti() {
    Toto toto = Mockito.spy(new Toto());
    Mockito.doReturn(2).when(toto).executeToto(Mockito.any(Tutu.class));

    PowerMockito.whenNew(Toto.class).withAnyArguments().thenReturn(toto);

    Titi testedObject = new Titi();
    testedObject.executeTiti();
  }
}

但我最喜歡的選項是為Titi創建一個輔助構造函數,用於測試:

public Titi(){
  this.toto = new Toto();     
}

/** For testing only. Uses the passed Toto instance instead of a new one. */
Titi(Toto toto){
  this.toto = toto;
}

然后只需要你像這樣調整你的測試:

@Test public void testExecuteTiti(){
  Toto toto = Mockito.spy(new Toto());
  Mockito.doReturn(2).when(toto).executeToto(Mockito.any(Tutu.class));

  Titi testedObject = new Titi(toto);
  testedObject.executeTiti();
}

你似乎缺少的是你的Toto類間諜實際上從未被Titi類使用過。

在你的情況下我會做的是

1)重構Titi類以接受Toto作為構造函數中的依賴項。 這樣你就可以用任何Toto輕松創建Titi(並在你的單元測試中使用模擬)

2)如果選項1不可用,您可以執行以下操作:

public class Titi{
  private Toto toto;

  public Titi(){
     this.toto = new Toto();     
  }

  public void executeTiti(){
      //do some stuff
      Tutu tutu = new Tutu();
      int ret = getToto().executeToto(tutu);
      //do some stuff
  }

  //package private - used for overriding via spying 
  Toto getToto() {
      return toto;
  }
}

@RunWith(MockitoJUnitRunner.class)
public class TitiTest {

 @Test
 public void testExecuteTiti(){
   Toto toto = Mockito.mock(Toto.class);
   when(toto.executeToto(Mockito.any(Tutu.class)).thenReturn(2);

   Titi testedObject = new Titi();
   testedObject = spy(testedObject);
   doReturn(toto).when(testedObject).getToto();

   testedObject.executeTiti();
 }
}

這篇文章描述了使用單行方法或工廠輔助方法來測試不注入協作者的類。 https://code.google.com/p/mockito/wiki/MockingObjectCreation

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM