Mockito макет аннотации нескольких объектов - PullRequest
0 голосов
/ 03 июня 2018

Я пытаюсь понять mockito, но я застреваю, я пытаюсь смоделировать несколько объектов с помощью аннотации @Mock, но это не будет имитировать их.Он будет только издеваться над первым объектом (mockBoard).Если я буду издеваться над BoardFactory самостоятельно, используя mock (Boardfactory.class), он будет работать.Но я не понимаю, почему это не работает в @Mock?

@ExtendWith(MockitoExtension.class)
class MapParserTest {

//mocks just fine
@Mock private Board mockBoard;

//wont mock both factories, sets them to null
@Mock private BoardFactory mockBoardFactory;
@Mock private LevelFactory mockLevelFactory;

//this will work
//private BoardFactory mockBoardFactory = mock(BoardFactory.class);

private MapParser mapParser = new MapParser(mockLevelFactory, mockBoardFactory);
private List<Ghost> ghosts = new ArrayList<>();
private List<Square> startPositions = new ArrayList<>();

@Test
void testParseCharMatrix() {
    //Arrange
    char[][] mapMatrix = new char[1][];
    mapMatrix[0] = new char[]{'#'};

    //nullPointer exception thrown here
    when(mockBoardFactory.createBoard(any(Square[][].class))).thenReturn(mockBoard);

    //Act
    mapParser.parseMap(mapMatrix);

    //Assert
    verify(mockLevelFactory).createLevel(mockBoard, ghosts, startPositions);
}}

Ответы [ 2 ]

0 голосов
/ 04 июня 2018
private MapParser mapParser = new MapParser(mockLevelFactory, mockBoardFactory);

Здесь mockLevelFactory и mockBoardFactory будут всегда равны нулю, независимо от того, JUnit4, 5, @Rule или @ExtendWith.Зачем?Поскольку эта строка вызывается, как только создается экземпляр вашего тестового класса, задолго до того, как у Mockito появилась возможность запустить и поместить макеты в ваши аннотированные переменные:

  1. Test-Class получает экземпляр
  2. Выполняются следующие строки:

    private MapParser mapParser = new MapParser(mockLevelFactory, mockBoardFactory);
    private List<Ghost> ghosts = new ArrayList<>();
    private List<Square> startPositions = new ArrayList<>();

  3. Mockito создает следующие насмешки:

    @Mock private Board mockBoard;
    @Mock private BoardFactory mockBoardFactory;
    @Mock private LevelFactory mockLevelFactory;

  4. (через некоторое время) Фактический метод испытания называется

Вот почему mockLevelFactory и mockBoardFactory равны всегда null в вашем MapParser.Они не являются нулевыми в вашем тесте, но они равны нулевыми в тот момент, когда вы создаете MapParser.

Решение?Создайте экземпляр вашего MapParser позже, например, в методе @BeforeEach ...

@BeforeEach
public void beforeEach() {
   // This method gets called AFTER Mockito created the mocks
   mapParser = new MapParser(mockLevelFactory, mockBoardFactory);
}

... или просто в начале вашего метода тестирования (но это можно считать плохимстиль).

0 голосов
/ 04 июня 2018

Вы уверены, что первое поле действительно инициализировано?Если вы не запускаете тест с MockitoJUnitRunner, вам нужно инициализировать аннотированные поля тестового класса вручную, например, так:

@BeforeEach 
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}

В качестве примечания, даже если макеты созданы правильно,тогда я уверен, что поле mapParser будет правильно инициализировано.Скорее всего, mock вводятся после инициализации тестового класса, поэтому вы, вероятно, не можете использовать mocked field в конструкторе или в инициализаторах поля.Вам, вероятно, нужно инициализировать это поле в методе @BeforeEach, как это было в начале.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...