Spring @Mock注释的意义是什么?
我有一个关于在控制器测试中创建bean的问题。例如,有一个这样的测试Spring @Mock注释的意义是什么?,spring,spring-mvc,mockito,spring-test-mvc,springmockito,Spring,Spring Mvc,Mockito,Spring Test Mvc,Springmockito,我有一个关于在控制器测试中创建bean的问题。例如,有一个这样的测试 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {MainApplicationConfiguration.class, JPAConfig.class}) @WebAppConfiguration public class TestMainController { private MockMvc mockMvc;
@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);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(类={MainApplicationConfiguration.class,JPAConfig.class})
@WebAppConfiguration
公共类TestMainController{
私有MockMvc-MockMvc;
@以前
公共作废设置(){
initMocks(this);
mockMvc=MockMvcBuilders.standaloneSetup(mainController.build();
}
@注射模拟
专用主控制器;
@嘲弄
私人入口服务入口服务;
@自动连线
DBEntryRepository;
@试验
public void testEntryGet()引发异常{
列表响应_data=new ArrayList();
响应数据添加(新的数据库条目(1,1,“STR”,“DATE”);
Mockito.when(entryService.findAllEntries())
.然后返回(响应数据);
MvcResult result=mockMvc.perform(get(“/VT/entry/”)
.andExpect(status().isOk()).andReturn();
验证(entryService,次(1)).findAllEntries();
验证NomoreInteractions(entryService);
}
}
以及映射到上的控制器方法
/VT/入口/
@RequestMapping(value=“/entry/”,method=RequestMethod.POST)
public ResponseEntity createEntry(@RequestBody DBEntry entry,UriComponentsBuilder ucBuilder){
System.out.println(“创建条目”+entry.getNum());
试一试{
entryService.saveEntry(entry);
entryService.refreshEntryService();
}捕获(例外e){
e、 printStackTrace();
返回新的响应属性(HttpStatus.BAD_请求);
}
HttpHeaders=新的HttpHeaders();
headers.setLocation(ucBuilder.path(“/entry/{id}”).buildAndExpand(entry.getId()).toUri());
返回新的ResponseEntity(标题,HttpStatus.CREATED);
}
EntryService
使用@Service
注释和main应用程序配置进行注释。class
是使用@EnableWebMvc
和此EntryService
的扫描项目的配置
通过这一点,我想说明这个控制器在实际应用程序中确实使用了这个EntryService
,并且所有这些都通过MainApplicationConfiguration.class
进行了耦合
问题是:为什么带有@Mock
注释的entryService
最终出现在我测试执行范围内的控制器代码中?难道不应该只针对那个实例,并且控制器内部应该实例化另一个bean(EntryService),为什么这个注释模拟了该bean的所有出现(在测试范围内)?我在想,我应该编写整个其他上下文web上下文,而不是main applicationconfiguration.class
,在内部模拟它并替换当前定义。我完全搞不懂为什么这个简单的注释会做出这样的事情
如果有人能理解这个魔法,请说出@InjectMock和@Mock的区别是什么
谢谢你的关注!如果我的问题很愚蠢的话,我很抱歉。我很新,它可以工作,但我还没有魔法。在for@InjectMocks
中:
Mockito将尝试按顺序仅通过构造函数注入、setter注入或属性注入来注入mock
因此,由于EntryService
是控制器的依赖项,@InjectMocks
将尝试在测试类中找到EntryService
的模拟对象,并将其注入mainController
请注意,只会发生构造函数注入、setter注入或属性注入中的一种
@Mock将字段标记为Mock对象。
@InjectMock将模拟对象注入到标记的字段中,但标记的字段不是模拟。这不是问题主要部分的答案。@Alex我的评论中包含了差异。你可以从中看到更多。你知道,你试图引用一些东西,但这篇引用并不能回答这个问题(:谢谢你的努力!我的EntryService用@Mock annotation注释。@Alex不是你的问题“为什么
EntryService
用@Mock
注释在我的测试执行范围内出现在我的控制器代码中?”?它位于控制器中,因为main控制器上的@InjectMocks
注释。
@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);
}