725 Stimmen

Unterschied zwischen @Mock und @InjectMocks

Was ist der Unterschied zwischen @Mock und @InjectMocks im Mockito-Framework?

860voto

Tom Verelst Punkte 14974

@Mock erstellt ein Mock-Objekt. @InjectMocks erstellt eine Instanz der Klasse und injiziert die Mock-Objekte, die mit den @Mock (oder @Spy) Annotationen erstellt wurden, in diese Instanz.

Bitte beachten Sie, dass Sie @RunWith(MockitoJUnitRunner.class) oder Mockito.initMocks(this) verwenden müssen, um diese Mock-Objekte zu initialisieren und sie zu injizieren (JUnit 4).

Bei JUnit 5 müssen Sie @ExtendWith(MockitoExtension.class) verwenden.

@RunWith(MockitoJUnitRunner.class) // JUnit 4
// @ExtendWith(MockitoExtension.class) für JUnit 5
public class SomeManagerTest {

    @InjectMocks
    private SomeManager someManager;

    @Mock
    private SomeDependency someDependency; // dieses wird in someManager injiziert

     // tests...

}

450voto

aldok Punkte 15755

Dies ist ein Beispielcode dafür, wie @Mock und @InjectMocks funktionieren.

Angenommen, wir haben die Klassen Game und Player.

class Game {

    private Player player;

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

    public String attack() {
        return "Spieler greift an mit: " + player.getWeapon();
    }

}

class Player {

    private String weapon;

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

    String getWeapon() {
        return weapon;
    }
}

Wie Sie sehen, benötigt die Klasse Game die Klasse Player, um einen Angriff durchzuführen.

@RunWith(MockitoJUnitRunner.class)
class GameTest {

    @Mock
    Player player;

    @InjectMocks
    Game game;

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

        assertEquals("Spieler greift an mit: Schwert", game.attack());
    }

}

Mockito wird eine Player-Klasse und ihr Verhalten mit den Methoden when und thenReturn mocken. Schließlich wird Mockito mit @InjectMocks diesen Player in das Game einfügen.

Beachten Sie, dass Sie nicht einmal ein neues Game-Objekt erstellen müssen. Mockito fügt es für Sie ein.

// das müssen Sie nicht machen
Game game = new Game(player);

Durch die Verwendung der Annotation @Spy erhalten wir dasselbe Verhalten. Auch wenn der Attributname unterschiedlich ist.

@RunWith(MockitoJUnitRunner.class)
public class GameTest {

  @Mock Player player;

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

  @InjectMocks Game game;

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

    enemies.add("Drache");
    enemies.add("Ork");

    assertEquals(2, game.numberOfEnemies());

    assertEquals("Spieler greift an mit: Schwert", game.attack());
  }
}

class Game {

  private Player player;

  private List opponents;

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

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

  // ...

Dies liegt daran, dass Mockito die Type-Signatur der Game-Klasse überprüfen wird, die Player und List ist.

90voto

In Ihrer Testklasse sollte die getestete Klasse mit @InjectMocks annotiert sein. Dies teilt Mockito mit, in welche Klasse Mocks eingefügt werden sollen:

@InjectMocks
private SomeManager someManager;

Von da an können wir angeben, welche spezifischen Methoden oder Objekte innerhalb der Klasse, in diesem Fall SomeManager, durch Mocks ersetzt werden:

@Mock
private SomeDependency someDependency;

In diesem Beispiel wird SomeDependency innerhalb der Klasse SomeManager gemockt.

70voto

Mik378 Punkte 21539

@Mock Annotation mockt das betroffene Objekt.

@InjectMocks Annotation ermöglicht es, die verschiedenen (und relevanten) Mocks, die von @Mock erstellt wurden, in das zugrunde liegende Objekt einzufügen.

Beide ergänzen sich gegenseitig.

34voto

sana Punkte 725
  • @Mock erstellt eine Mock-Implementierung für die Klassen, die Sie benötigen.
  • @InjectMock erstellt eine Instanz der Klasse und fügt die Mocks ein, die mit den Annotationen @Mock markiert sind.

Zum Beispiel

@Mock
StudentDao studentDao;

@InjectMocks
StudentService service;

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

Hier benötigen wir die DAO-Klasse für die Service-Klasse. Wir mocken sie und fügen sie in die Instanz der Service-Klasse ein. Ähnlich können in Spring Framework alle mit @Autowired annotierten Beans in jUnits gemockt und in Ihren Bean durch @InjectMocks eingesetzt werden.

Die Methode MockitoAnnotations.initMocks(this) initialisiert diese Mocks und fügt sie für jede Testmethode ein, daher muss sie in der setUp()-Methode aufgerufen werden.

Dieser Link enthält ein gutes Tutorial für das Mockito Framework

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X