@Mock注解的意义是什么?
What is sense of @Mock annotation?
我有一个关于在控制器测试中创建 bean 的问题。比如有这样一个测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MainApplicationConfiguration.class, JPAConfig.class})
@WebAppConfiguration
public class TestMainController {
private MockMvc mockMvc;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(mainController).build();
}
@InjectMocks
private MainController mainController;
@Mock
private EntryService entryService;
@Autowired
DBEntryRepository repository;
@Test
public void testEntryGet() throws Exception {
List<DBEntry> response_data = new ArrayList<>();
response_data.add(new DBEntry(1, 1, "STR", "DATE"));
Mockito.when(entryService.findAllEntries())
.thenReturn(response_data);
MvcResult result = mockMvc.perform(get("/VT/entry/"))
.andExpect(status().isOk()).andReturn();
verify(entryService, times(1)).findAllEntries();
verifyNoMoreInteractions(entryService);
}
}
和映射到
的控制器方法
/VT/entry/
@RequestMapping(value = "/entry/", method = RequestMethod.POST)
public ResponseEntity<Void> createEntry(@RequestBody DBEntry entry, UriComponentsBuilder ucBuilder) {
System.out.println("Creating entry " + entry.getNum());
try {
entryService.saveEntry(entry);
entryService.refreshEntryService();
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<Void>(HttpStatus.BAD_REQUEST);
}
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/entry/{id}").buildAndExpand(entry.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
EntryService
使用 @Service
注释进行注释,MainApplicationConfiguration.class
是使用 @EnableWebMvc
的配置,并为此 EntryService
.
扫描项目
我想表明这个控制器在实际应用中确实使用了这个 EntryService
,并且所有这些都由 MainApplicationConfiguration.class
耦合。
问题是:为什么带有 @Mock
注释的 entryService
最终出现在我的测试执行范围内的控制器代码中?它不应该只针对那个实例并且应该在控制器内部实例化另一个bean(EntryService),为什么这个注释模拟了那个bean的所有出现(在测试范围内)?我在想,我应该编写整个其他上下文 web-context 而不是 MainApplicationConfiguration.class
来在内部模拟它并替换当前定义。我非常困惑为什么这个简单的注释会做出这样的事情。
如果有人能理解这个魔法,请说出@InjectMock 和@Mock 之间的区别是什么?
感谢您的关注!对不起,如果我的问题很愚蠢。我很新,它有效,但我还没有魔法。
在 documentation 中 @InjectMocks
:
Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order
因此,由于 EntryService
是您的控制器的依赖项,@InjectMocks
将尝试在您的测试 class 中找到 EntryService
的模拟对象并将其注入 mainController
.
请注意,只有 constructor injection, setter injection, or property injection
中的一个会发生。
@Mock 将字段标记为模拟对象。
@InjectMocks 给标记的字段注入mock对象,但是标记的字段不是mock。
我有一个关于在控制器测试中创建 bean 的问题。比如有这样一个测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MainApplicationConfiguration.class, JPAConfig.class})
@WebAppConfiguration
public class TestMainController {
private MockMvc mockMvc;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(mainController).build();
}
@InjectMocks
private MainController mainController;
@Mock
private EntryService entryService;
@Autowired
DBEntryRepository repository;
@Test
public void testEntryGet() throws Exception {
List<DBEntry> response_data = new ArrayList<>();
response_data.add(new DBEntry(1, 1, "STR", "DATE"));
Mockito.when(entryService.findAllEntries())
.thenReturn(response_data);
MvcResult result = mockMvc.perform(get("/VT/entry/"))
.andExpect(status().isOk()).andReturn();
verify(entryService, times(1)).findAllEntries();
verifyNoMoreInteractions(entryService);
}
}
和映射到
的控制器方法/VT/entry/
@RequestMapping(value = "/entry/", method = RequestMethod.POST)
public ResponseEntity<Void> createEntry(@RequestBody DBEntry entry, UriComponentsBuilder ucBuilder) {
System.out.println("Creating entry " + entry.getNum());
try {
entryService.saveEntry(entry);
entryService.refreshEntryService();
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<Void>(HttpStatus.BAD_REQUEST);
}
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/entry/{id}").buildAndExpand(entry.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
EntryService
使用 @Service
注释进行注释,MainApplicationConfiguration.class
是使用 @EnableWebMvc
的配置,并为此 EntryService
.
我想表明这个控制器在实际应用中确实使用了这个 EntryService
,并且所有这些都由 MainApplicationConfiguration.class
耦合。
问题是:为什么带有 @Mock
注释的 entryService
最终出现在我的测试执行范围内的控制器代码中?它不应该只针对那个实例并且应该在控制器内部实例化另一个bean(EntryService),为什么这个注释模拟了那个bean的所有出现(在测试范围内)?我在想,我应该编写整个其他上下文 web-context 而不是 MainApplicationConfiguration.class
来在内部模拟它并替换当前定义。我非常困惑为什么这个简单的注释会做出这样的事情。
如果有人能理解这个魔法,请说出@InjectMock 和@Mock 之间的区别是什么?
感谢您的关注!对不起,如果我的问题很愚蠢。我很新,它有效,但我还没有魔法。
在 documentation 中 @InjectMocks
:
Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order
因此,由于 EntryService
是您的控制器的依赖项,@InjectMocks
将尝试在您的测试 class 中找到 EntryService
的模拟对象并将其注入 mainController
.
请注意,只有 constructor injection, setter injection, or property injection
中的一个会发生。
@Mock 将字段标记为模拟对象。 @InjectMocks 给标记的字段注入mock对象,但是标记的字段不是mock。