【问题标题】:What is sense of @Mock annotation?@Mock 注释的意义是什么?
【发布时间】:2018-06-10 18:31:50
【问题描述】:

我有一个关于在控制器测试中创建 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/入口/

@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 有什么区别?

感谢您的关注!对不起,如果我的问题很愚蠢。我很新,它可以工作,但我还没有魔法。

【问题讨论】:

    标签: spring spring-mvc mockito spring-test-mvc springmockito


    【解决方案1】:

    documentation 中为@InjectMocks

    Mockito 将尝试仅通过构造函数注入、setter 注入或属性注入的顺序注入模拟

    因此,由于EntryService 是您的控制器的依赖项,@InjectMocks 将尝试在您的测试类中找到EntryService 的模拟对象并将其注入mainController

    请注意,只会出现constructor injection, setter injection, or property injection 之一。

    @Mock 将字段标记为模拟对象。 @InjectMocks 将 mock 对象注入到标记的字段中,但标记的字段不是 mock。

    【讨论】:

    • 这不是问题主要部分的答案。
    • @Alex 差异包含在我的评论中。您可以在 post 中看到更多信息。
    • 你知道,你试图引用一些东西,但这个引用不是这个问题的答案(:感谢你的努力!我的 EntryService 用@Mock 注释进行了注释。
    • @Alex 你的问题不是“为什么带有@Mock 注释的entryService 最终出现在我的测试执行范围内的控制器代码中?”?由于mainController 上的@InjectMocks 注释,它在您的控制器中。
    猜你喜欢
    • 2011-01-07
    • 2014-05-02
    • 2023-03-06
    • 2014-06-27
    • 2018-01-02
    • 1970-01-01
    • 2019-05-10
    • 2010-11-29
    • 1970-01-01
    相关资源
    最近更新 更多