简体   繁体   English

Mockito模拟注释多个对象

[英]Mockito mock annotation multiple objects

I'm trying to understand mockito but I'm getting stuck, im trying to mock multiple objects using the @Mock annotation, but it will not mock them. 我试图理解模仿,但我陷入困境,试图通过@Mock注释模仿多个对象,但不会模仿它们。 It will only mock the first object (mockBoard). 它只会模拟第一个对象(mockBoard)。 If I mock the BoardFactory myself using mock(Boardfactory.class) it will work. 如果我自己使用模拟对象(Boardfactory.class)模拟BoardFactory,它将起作用。 But i dont understand why it wont work in the @Mock? 但是我不明白为什么它不能在@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);
}}
private MapParser mapParser = new MapParser(mockLevelFactory, mockBoardFactory);

Here, mockLevelFactory and mockBoardFactory will always be null, no matter if JUnit4, 5, @Rule or @ExtendWith . 在这里,无论JUnit4、5, @Rule还是@ExtendWithmockLevelFactorymockBoardFactory 始终为null。 Why? 为什么? Because that line gets called as soon as your test class is instantiated, long before Mockito had a chance to run and put mocks into your annotated variables: 因为该行在实例化测试类后立即被调用,所以在Mockito有机会运行并将模拟放入已注释的变量之前很久:

  1. Test-Class gets instantiated 测试类被实例化
  2. The following lines get executed: 执行以下行:

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

  3. Mockito creates the following mocks: Mockito创建以下模拟:

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

  4. (some time later) The actual test method is called (稍后)实际的测试方法称为

This is why mockLevelFactory and mockBoardFactory are always null in your MapParser . 这就是为什么您的mockLevelFactorymockBoardFactory 始终为 null的MapParser They are not null in your test, but they are null at the moment when you create your MapParser . 它们在您的测试中不为null,但是在您创建MapParser null。

The solution? 解决方案? Create the instance of your MapParser later, for example in a @BeforeEach method... 稍后,例如在@BeforeEach方法中,创建MapParser的实例。

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

...or also simply at the start of your test method (but one could consider that bad style). ...或者也可以只是在测试方法的开始(但您可以考虑这种不良样式)。

Are you sure the first field is actually initialized? 您确定第一个字段实际上已初始化吗? Unless you run the test with MockitoJUnitRunner , you need to initialize the annotated fields of the test class manually, for example like this: 除非使用MockitoJUnitRunner运行测试, MockitoJUnitRunner需要手动初始化测试类的带注释的字段,例如:

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

As a side note, even if the mocks are created correctly, then I'm note sure if the field mapParser will be initialized correctly. 附带说明一下,即使正确创建了mapParser也请注意是否会正确初始化mapParser字段。 It's likely that mocks are injected after the test class has been initialized, so you probably can't use mocked field in the constructor or in field initializers. 可能在初始化测试类之后注入了模拟,因此您可能无法在构造函数或字段初始化器中使用模拟字段。 You probably need to initialize that field in a @BeforeEach method, like you had in the beginning. 您可能需要像在开始时一样,在@BeforeEach方法中初始化该字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM