[英]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
还是@ExtendWith
, mockLevelFactory
和mockBoardFactory
始终为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有机会运行并将模拟放入已注释的变量之前很久:
The following lines get executed: 执行以下行:
private MapParser mapParser = new MapParser(mockLevelFactory, mockBoardFactory);
private List<Ghost> ghosts = new ArrayList<>();
private List<Square> startPositions = new ArrayList<>();
Mockito creates the following mocks: Mockito创建以下模拟:
@Mock private Board mockBoard;
@Mock private BoardFactory mockBoardFactory;
@Mock private LevelFactory mockLevelFactory;
(some time later) The actual test method is called (稍后)实际的测试方法称为
This is why mockLevelFactory
and mockBoardFactory
are always null in your MapParser
. 这就是为什么您的mockLevelFactory
和mockBoardFactory
始终为 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.