簡體   English   中英

junit測試類的以下代碼

[英]junit test class for the following code

如何為Phone對象模擬對象。

波紋管

public class Fortest {

  UserDao userdao = new UserDao();
  Phone name = new Phone();
  public String handleUser(User user) {

    String returncode="failed";
    //User usr = new User("bob");
    String username=user.getUsername();
    String pass=user.getPass();
    System.out.println("username and password : "+username+" : "+pass);

    Phone name = new Phone();
    String ph = name.getA();
    System.out.println("ph "+ph);

    if(ph.equalsIgnoreCase("test")){
      System.out.println("A "+ph);
      returncode="done";
    }
    System.out.println("returning "+returncode);

    return  returncode;
    //System.out.println("name "+name.toString());
    //System.out.println(name.getA());
  }
}

謝謝

你不知道 模擬的規則之一是:永遠不要模擬實體或值對象。 如果您需要違反此規則,則意味着您可能存在設計缺陷。

如果需要模擬new ,則需要將工廠傳遞給對象,然后模擬工廠。 一個非常常見的示例是何時需要模擬Date對象,這在另一個問題中得到了很好的解釋: 如何模擬Date類的默認構造函數 (請檢查第一個答案)。

附帶說明,調用看起來不正確的Phone name ... mmm實例。

首先,我要做一些假設。 user.getUsername()user.getPass()沒有副作用。 System.out.println對您並不重要。

這樣,您的課程變成了:

public class Fortest {
    Phone name = new Phone();

    public String handleUser(User user) {
        String ph = name.getA();

        if(ph.equalsIgnoreCase("test")){
            return "done";
        }

        return  "failed";

    } 
}

因此,您的測試有兩個條件。 phone.getA()是“ test”,則返回“ done”,否則返回“ failed”。

那么如何設置設置為“ getA ”。 可以肯定的是,我們需要能夠從測試中設置“名稱”。 為此,我們需要“注入”它(我們可以通過其他多種方式來實現它,但是我喜歡注入)。 我會用Guice,許多人會用Spring。 有些人會使用其他注入框架之一。 但是在測試中,我們大多數人會使用手動注射。

public class Fortest {
    Phone name;
    Fortest(Phone name) {
        this.name = name;
    }

    public String handleUser(User user) {
        String ph = name.getA();

        if(ph.equalsIgnoreCase("test")){
            return "done";
        }

        return  "failed";

    } 
}


public class TestFortest {
   @Before
   public void before() {
          name = ; //... 
          subject = new Fortest(name);
   }
}

現在測試非常簡單:

public void whenTestModeIsEnabledThenReturnDone() {
     setPhoneIntoTestMode();
     String actual = subject.handleUser(null);
     assertEquals(actual, "done");
}

public void whenTestModeIsDisabledThenReturnFailed() {
     setPhoneIntoLiveMode();
     String actual = subject.handleUser(null);
     assertEquals(actual, "failed");
}

setPhoneIntoTestMode / setPhoneIntoLiveMode的實現將取決於Phone復雜程度。 如果它比我們要復雜的話,我們會以某種方式(模擬,存根等)看待它。 這可能是您編寫的代碼塊,也可能使用了Mocketo之類的工具。

如果Phone對象很簡單,並且具有或可以具有“ setA ”方法,則只需使用它。

我確定以后您將需要userdao 屆時將做同樣的事情。 注入並模擬/設置對象。

使用EasyMock非常容易進行類模擬 它在內部利用cglib進行類模擬。 EasyMock可以模擬接口類(類模擬)。 請參閱文檔

因此,要模擬您的Phone,只需調用createMock(Phone.class):

Phone phoneMock = createMock(Phone.class);

正如Augusto所說,利用類模擬並不是一個很好的設計。 更好的方法是對接口進行編程並使用依賴項注入框架。

因此,您需要執行以下選項之一,以將userdao注入字段nameuserdao (我假設您可以使用new Phone字段實例,而不是在方法中創建的實例。

  1. 不要直接在代碼中調用構造函數,而應通過setter使用字段注入。 這將允許您的測試提供兩個類的模擬實例。 如果必須在方法中創建新實例,則考慮使用可以模擬的工廠。

  2. 為兩個字段提供默認范圍設置器方法。 這些方法僅用於測試目的。

  3. 使用Refection將字段設置為模擬實例。 一個簡單的方法就是使用Spring的ReflectionTestUtils。

一旦其中之一到位,您就可以提供模擬實例(也許使用Mockito)來驅動您要測試的行為。 我建議,如果可行的話,選項1是最好的,然后是選項3。但是,選項3的缺點是測試取決於私有字段的名稱。

然后...

Phone phone = Mockito.mock(Phone.class);
Mockito.when(phone.getA()).thenReturn("blah");
objectUnderTest.setPhone(phone);

objectUnderTest.handleUser(...);

暫無
暫無

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

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