【问题标题】:Mock service in Spring MVCSpring MVC 中的模拟服务
【发布时间】:2018-01-29 10:54:23
【问题描述】:

我在 Spring MVC 中模拟服务时遇到问题:

@Controller
public class CompanyController {

  @Autowired
  private CompanyService companyService;

  @Autowired
  private CompanyRelationService companyRelationService;

  @GetMapping({"/", "/companies"})
  public String displayCompanies(Model model) {
    model.addAttribute("company", new Company());
    List<Company> companies = companyService.findAll();
    model.addAttribute("companies", companies);
    return "companies";
  }
}

和测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class CompanyTests {

@Autowired
private WebApplicationContext webApplicationContext;

@Mock
CompanyService companyServiceMock;

private MockMvc mockMvc;


@Before
public void setUp() {
    Mockito.reset(companyServiceMock);
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    MockitoAnnotations.initMocks(this);
}


@Test
public void shouldListAllCompanies() throws Exception {
    Company company1 = new Company("company1", new Address());
    Company company2 = new Company("company2", new Address());

    when(companyServiceMock.findAll()).thenReturn(Arrays.asList(company1, company2));

    mockMvc.perform(get("/companies"))
            .andExpect(status().isOk())
            .andExpect(view().name("companies"))
            .andExpect(model().attribute("companies", hasSize(2)))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("company1")))
            )))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("company2"))
                    )
            )));

}
}

问题是为什么我从真实服务而不是模拟(company1,company2)中获取公司:

java.lang.AssertionError: Model attribute 'companies'
     Expected: a collection containing (hasProperty("name", is "company1"))
     but: hasProperty("name", is "company1") property 'name' was "companyFromRealService", 
     hasProperty("name", is "company1") property 'name' was "CompanyFromRealService2"

更新了 Test 类,删除了 setUp 并将 @Bean 更改为 @MockBean,但仍保留 @SpringBootTest 并且它可以工作:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class CompanyTests {

@MockBean
private CompanyService companyServiceMock;

@Autowired
private MockMvc mockMvc;

@Test
@WithMockUser(roles = "ADMIN")
public void shouldListAllCompanies() throws Exception {
    Company company1 = new Company("company1", new Address());
    Company company2 = new Company("company2", new Address());

    when(companyServiceMock.findAll()).thenReturn(Arrays.asList(company1, company2));

    mockMvc.perform(get("/companies"))
            .andExpect(status().isOk())
            .andExpect(view().name("companies"))
            .andExpect(model().attribute("companies", hasSize(2)))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("companyFromRealService1")))
            )))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("companyFromRealService2"))
                    )
            )));
}

}

【问题讨论】:

  • get("/companies") 上会发生什么?我想这叫真正的服务。用模拟结果替换调用
  • 当然他们不会...你正在反对框架。 Spring Boot 做了很多工作来注入和模拟依赖项,而您要做的第一件事就是销毁所有这些工作。删除您的 @Before 方法并将 @Autowired 放在 MockMvc 字段中并重新开始测试。
  • @StanislavL 我该怎么做?
  • 您使用的是哪个 Spring Boot 版本?将@AutoConfigureMockMvc 添加到您的测试类。
  • @Mock 替换为@MockBean

标签: spring testing spring-boot mocking mockito


【解决方案1】:

首先,如果您只是测试应用程序的控制器切片,则应使用@WebMvcTest 注释而不是@SpringBootTest(您可以找到更多信息here)。你可以像这样使用它:@WebMvcTest(CompanyController.class)

其次,您为什么在setUp() 方法中遇到MockMvc 的麻烦?您可以按照人们在 cmets 和 @Autowire MockMvc 中的建议删除 setUp 方法。

最后,当您使用 spring boot 时,最好使用 @MockBean 而不是 @Mock,后者是它在 spring 库中的包装版本。

【讨论】:

  • 感谢您的回答。我做到了,现在我有 java.lang.IllegalStateException: Failed to load ApplicationContext 错误。
  • @Helosze,你能用当前的测试课程更新你的答案吗?
  • 当我把Mock改成MockBean,但是没有把SpringBootTest改成WebMvcTest,现在可以了
  • @Helosze,乐于助人。您可能仍希望将您的测试课程最终形式更新为您的问题,以便人们在将来遇到此问题时可以轻松看到它。如果它解决了你的问题,你可以接受这个答案:)
  • 是的,当然。我已经编辑过了。但也许把这个 SpringBootTest 改成 WebMvcTest 会好点? :) 感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
  • 1970-01-01
  • 2016-08-18
  • 1970-01-01
  • 2021-07-12
  • 2021-05-02
  • 2013-04-16
相关资源
最近更新 更多