【发布时间】: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