2016-08-16 121 views
2

我想模擬外部API調用,但與代碼結構我不知道mockito是否會幫助。使用mockito模擬基類中的方法或模擬靜態方法

我有一個SimpleController:

public class SimpleController extends Anothercontroller 
{ 
    @RequestMapping("/classA") 
    { 
    ....... 
    String response = postCall(url, .....); 
    } 
} 

public class AnotherController 
{ 
    public String postCall (String url, ......) 
    { 
    //This is the apache library to make post calls 
    return WebUtil.post(......); 
    } 
} 

所以現在我需要模擬postCall這是外部服務的調用。

在這裏,我可以在2個地方嘲笑:

1)postCall()在SimpleController,howevere我不知道該怎麼做,因爲它有利於繼承了組成。

2)WebUtil.post(.....)但是我不知道mockito如何模擬靜態方法。

我不想重構代碼結構,因爲還有很多其他代碼依賴於它。

回答

1

1)在SimpleController中的postCall(),howevere我不知道如何做 ,因爲它有利於繼承組合。

這可能與Mockito使用間諜。間諜是使用真實方法的對象的模擬,除非另有規定。

// spyController will use real methods expect for postCall() 
SimpleController spyController = Mockito.spy(new SimpleController()); 
Mockito.doReturn("mockedString").when(spyController).postCall(); 

2)WebUtil.post(.....),但是我不知道怎麼的Mockito可以模擬一個 靜態方法。

這是不可能的Mockito,但有2個工作arrounds:

  1. 使用PowerMock,這使得靜態的嘲諷。
  2. 重構您的代碼以不直接調用靜態方法。這已經在@ mdewit的回答中解釋過了,所以我只是讓你閱讀那裏的細節。

就我個人而言,我認爲重構是最乾淨的解決方案,因爲有static dependencies is evil。如果出於任何原因你不能或不想改變你的產品代碼,那麼比Mockito.spy()是一個好方法。

1

如果你被允許修改AnotherController,你可以做到以下幾點:首先,你換WebUtil另一個類中,像這樣:

public class WebUtilWrapper { 
    String post(.....) { 
      return WebUtil.post(.....); 
    } 
} 

然後,一個構造函數添加到AnotherController這需要WebUtilWrapper作爲參數。此構造函數將用於您的單元測試:

public class AnotherController { 
    private WebUtilWrapper wrapper; 

    public AnotherController() { 
      //default constructor 
      this(new WebUtilWrapper());    
    } 

    public AnotherController(WebUtilWrapper wrapper) { 
      this.wrapper = wrapper; 
    } 

    public String postCall (String url, ......) { 
      //This is the apache library to make post calls 
      return this.wrapper.post(......); 
    } 
} 

最後還要將參數化的構造函數添加到您的SimpleController。

public class SimpleController extends Anothercontroller { 
     public SimpleController() { 
      super(); 
     } 

     public SimpleController(WebUtilWrapper wrapper) { 
      super(wrapper); 
     } 
     . 
     . 
     . 

現在,您可以在單元測試中模擬WebUtilWrapper(而不是WebUtil)。剩下的代碼將正常工作,因爲默認構造函數仍然可用。