2013-05-09 55 views
200

Mockito框架中的@Mock@InjectMocks有什麼區別?@Mock和@InjectMocks的區別

+0

有用的資源https://tedvinke.wordpress。com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/ – Dushman 2017-10-11 05:26:51

回答

249

@Mock創建一個模擬。 @InjectMocks創建該類的一個實例,並將使用@Mock(或@Spy)註釋創建的模仿注入到此實例中。請注意,您必須使用@RunWith(MockitoJUnitRunner.class)Mockito.initMocks(this)來初始化這些模擬並注入它們。

@RunWith(MockitoJUnitRunner.class) 
public class SomeManagerTest { 

    @InjectMocks 
    private SomeManager someManager; 

    @Mock 
    private SomeDependency someDependency; // this will be injected into someManager 

    //tests... 

} 
37

@Mock註釋嘲笑的關注對象。

@InjectMocks批註允許向底層對象注入由@Mock創建的不同(和相關)模擬。

兩者都是互補的。

+1

它們可以在同一個對象上串聯使用嗎? – 2017-04-24 20:03:27

+1

你有一個你的要求的小例子? – Mik378 2017-04-24 21:19:50

+0

我有一個需要被窺探的類(通過Mockito Spy),並且這個類有一個構造函數。所以我想用'@InjectMocks'來構建這個類,並對它進行窺探。 – 2017-04-25 13:17:00

11

A「嘲諷框架」,它的Mockito是基於,是一個框架,讓你創建模擬對象的能力(在舊條款這些對象可以被稱爲分流器,因爲他們作爲分流工作的dependend功能) 換句話說,模擬對象用於模擬代碼所依賴的真實對象,您可以使用模擬框架創建代理對象。 通過在測試中,你基本上是正常的單元測試要整合的測試中使用模擬對象

的Mockito是Java的MIT許可下發布的開源測試框架,它是一種「嘲諷框架」,可以讓你寫美麗的測試與乾淨和簡單的API。 Java空間中有許多不同的模擬框架,但基本上有兩種主要類型的模擬對象框架,一種是通過代理實現的,另一種是通過類重新映射實現的。

如Spring依賴注入框架,讓您無需修改​​任何代碼注入您的代理對象,模擬對象應該被稱爲一定的方法,它會返回預期的結果。

@InjectMocks註釋嘗試實例化測試對象實例,並將註釋爲@Mock@Spy的字段注入到測試對象的專用字段中。

MockitoAnnotations.initMocks(this)調用,重置測試對象並重新初始化模擬,所以請記住在您的@Before/@BeforeMethod註釋中有這個。

6

您使用@Tom提到的方法獲得的一個優點是您不必在SomeManager中創建任何構造函數,因此限制客戶端實例化它。

@RunWith(MockitoJUnitRunner.class) 
public class SomeManagerTest { 

    @InjectMocks 
    private SomeManager someManager; 

    @Mock 
    private SomeDependency someDependency; // this will be injected into someManager 

    //You don't need to instantiate the SomeManager with default contructor at all 
    //SomeManager someManager = new SomeManager();  
    //Or SomeManager someManager = new SomeManager(someDependency); 

    //tests... 

} 

無論是它的一個很好的做法與否取決於你的應用程序設計。

+0

如果someManager有3個不同的構造函數,它將如何知道使用哪一個? – j2emanue 2017-02-14 23:51:23

+0

然後你如何驗證** someManager **上的內容,如果它沒有被模擬? – 2017-04-24 20:04:39

40

在你的測試類中,被測試的類應該用@InjectMocks註釋。這告訴的Mockito哪個類注入嘲笑成:

@InjectMocks 
private SomeManager someManager; 

從此,我們可以指定類中的特定方法或對象,在這種情況下SomeManager,將與嘲笑取代:

@Mock 
private SomeDependency someDependency; 

在此示例中,SomeManager類中的SomeDependency將被模擬。

+3

如果someManager具有多於一個的構造函數,這將工作嗎?如果someManager有5個構造函數會怎麼知道你想使用哪一個呢? – j2emanue 2017-02-14 23:52:40

18

我會告訴你一個關於@Mock@InjectMocks如何工作的示例代碼。

假設我們有GamePlayer類。

class Game { 

    private Player player; 

    public Game(Player player) { 
     this.player = player; 
    } 

    public String attack() { 
     return "Player attack with: " + player.getWeapon(); 
    } 

} 

class Player { 

    private String weapon; 

    public Player(String weapon) { 
     this.weapon = weapon; 
    } 

    String getWeapon() { 
     return weapon; 
    } 
} 

正如你看到的,Game類需要Player執行attack

@RunWith(MockitoJUnitRunner.class) 
class GameTest { 

    @Mock 
    Player player; 

    @InjectMocks 
    Game game; 

    @Test 
    public void attackWithSwordTest() throws Exception { 
     Mockito.when(player.getWeapon()).thenReturn("Sword"); 

     assertEquals("Player attack with: Sword", game.attack()); 
    } 

} 

會的Mockito嘲笑一個Player類和它的使用whenthenReturn法的行爲。最後,使用@InjectMocks Mockito將把Player放入Game

請注意,您甚至不必創建new Game對象。 Mockito將爲您注入它。

// you don't have to do this 
Game game = new Game(player); 

我們也將使用@Spy註釋得到相同的行爲。即使屬性名稱不同。

@RunWith(MockitoJUnitRunner.class) 
public class GameTest { 

    @Mock Player player; 

    @Spy List<String> enemies = new ArrayList<>(); 

    @InjectMocks Game game; 

    @Test public void attackWithSwordTest() throws Exception { 
    Mockito.when(player.getWeapon()).thenReturn("Sword"); 

    enemies.add("Dragon"); 
    enemies.add("Orc"); 

    assertEquals(2, game.numberOfEnemies()); 

    assertEquals("Player attack with: Sword", game.attack()); 
    } 
} 

class Game { 

    private Player player; 

    private List<String> opponents; 

    public Game(Player player, List<String> opponents) { 
    this.player = player; 
    this.opponents = opponents; 
    } 

    public int numberOfEnemies() { 
    return opponents.size(); 
    } 

    // ... 

這是因爲會的Mockito檢查遊戲類,這是PlayerList<String>Type Signature

我希望清除一些混淆。

4
  • @Mock爲您需要的類創建一個模擬實現。
  • @InjectMock創建該類的一個實例,並將標記有註釋@Mock的嘲諷注入到該實例中。

例如

@Mock 
StudentDao studentDao; 

@InjectMocks 
StudentService service; 

@Before 
public void setUp() throws Exception { 
    MockitoAnnotations.initMocks(this); 
} 

在這裏我們需要對服務類的DAO類。所以,我們嘲笑它並將其注入服務類實例中。 同樣,在Spring框架中,所有@Autowired bean都可以在jUnits中被@Mock模擬,並通過@InjectMocks注入到bean中。

MockitoAnnotations.initMocks(this)方法初始化這些模擬併爲每個測試方法注入它們,所以需要在setUp方法中調用它們。

This link has a good tutorial for Mockito framework