spring - Spring MVC 中的模拟服务

标签 spring testing spring-boot mocking mockito

我在 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"))
                    )
            )));
}

}

最佳答案

首先,如果您只是测试应用程序的 Controller 部分,则应该使用 @WebMvcTest 注解而不是 @SpringBootTest (您可以找到更多信息 here ) 。您可以像这样使用它:@WebMvcTest(CompanyController.class)

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

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

关于spring - Spring MVC 中的模拟服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45795854/

相关文章:

java - 无法统计应用程序。将 SpringBoot 从 2.0.6.RELEASE 更新到 2.1.0.RELEASE 后

java - 使用 "@"获取系统属性

java - Spring : Injection of autowired dependencies failed

testing - 为什么需要原型(prototype)测试?

java - 测试 Thymeleaf 表单/Spring MVC Controller 交互的最佳方法

java - 如何高效处理Spring中的错误: Could not resolve view with name 'forward:/oauth/error'

php - 您将如何为此类类(class)编写测试?

spring - 主模块和测试模块的单个 application.properties

java - 为什么 SpEL 在 Spring Boot 和 Spring Cloud Stream @SendTo 中不起作用

spring-boot - Jooq Java API,在选择查询中将日期时间转换为时区