当前位置: 首页 > 知识库问答 >
问题:

在SpringBoot 1.4中测试Spring MVC切片的问题

韦德厚
2023-03-14

我正在试用新的Spring Boot 1.4 MVC测试功能。我有下面的控制器。

@Controller
public class ProductController {

  private ProductService productService;

  @Autowired
  public void setProductService(ProductService productService) {
    this.productService = productService;
  }

  @RequestMapping(value = "/products", method = RequestMethod.GET)
  public String list(Model model){
    model.addAttribute("products", productService.listAllProducts());
     return "products";
  }
}

我的最低ProductService实现是:

@Service
public class ProductServiceImpl implements ProductService {
  private ProductRepository productRepository;

  @Autowired
  public void setProductRepository(ProductRepository productRepository) {
    this.productRepository = productRepository;
  }

  @Override
  public Iterable<Product> listAllProducts() {
    return productRepository.findAll();
  }

}

ProductRepository的代码是:

public interface ProductRepository extends CrudRepository<Product,    
 Integer>{
}

我正在尝试使用新的@WebMvcTest来测试康罗尔。我的观点是胸片团队板。我的控制器测试是这样的:

@RunWith(SpringRunner.class)
@WebMvcTest(ProductController.class)

public class ProductControllerTest {
private MockMvc mockMvc;

@Before
public void setUp() {
    ProductController productController= new ProductController();       
    mockMvc = MockMvcBuilders.standaloneSetup(productController).build();
}

@Test
public void testList() throws Exception {        
mockMvc.perform(MockMvcRequestBuilders.get("/products"))                 
.andExpect(MockMvcResultMatchers.status().isOk())                
.andExpect(MockMvcResultMatchers.view().name("products"))             
 .andExpect(MockMvcResultMatchers.model().attributeExists("products"));               
 }
}

但是,在运行测试时,我得到了这个错误。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through method 'setProductService' parameter 0: No qualifying bean of type [guru.springframework.services.ProductService] found for dependency [guru.springframework.services.ProductService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [guru.springframework.services.ProductService] found for dependency [guru.springframework.services.ProductService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

我需要帮助解决问题,以便正确测试ProductController。如需对控制器进行更彻底的测试,请提供额外的建议和期望(),我们将不胜感激。

提前感谢。

共有3个答案

龙骏
2023-03-14

我没有自动连接MockMvc,而是在设置阶段像这样实例化了MockMvc对象。

protected void setUp() {
        mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
曹高轩
2023-03-14

您正在使用@WebMvcTest,同时也在手动配置MockMvc实例。这没有意义,因为@WebMvcTest的主要目的之一是为您自动配置MockMvc实例。此外,在手动配置中,您使用的是standaloneSetup,这意味着您需要完全配置正在测试的控制器,包括向其中注入任何依赖项。您没有这样做,这会导致NullPointerException

如果您想使用@WebMvcTest,我建议您这样做,您可以完全删除设置方法,并使用@Autowired字段注入一个自动配置的MockMvc实例。

然后,为了控制ProductController使用的ProductService,可以使用新的@MockBean注释创建一个mockProductService,然后将其注入ProductController

这些更改使您的测试类看起来像这样:

package guru.springframework.controllers;

import guru.springframework.services.ProductService;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@WebMvcTest(ProductController.class)
public class ProductControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private ProductService productService;

    @Test
    public void testList() throws Exception {
      mockMvc.perform(MockMvcRequestBuilders.get("/products"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                 .andExpect(MockMvcResultMatchers.view().name("products"))
                 .andExpect(MockMvcResultMatchers.model().attributeExists("products"))
               .andExpect(MockMvcResultMatchers.model().attribute("products",
                        Matchers.is(Matchers.empty())));

    }
}
田兴旺
2023-03-14

有兴趣加载完整应用程序的用户应尝试使用@SpringBootTest@AutoConfigureMockMvc结合使用,而不是@WebMvcTest

我为这个问题挣扎了很长一段时间,但最终我了解了全部情况
到目前为止,我在互联网上找到了许多教程,以及Spring的官方文档,说明您可以使用@WebMvcTest测试控制器;这是完全正确的,但仍然省略了一半的故事
正如此类注释的javadoc所指出的,@WebMvcTest仅用于测试控制器,根本不会加载应用程序的所有bean,这是出于设计
它甚至与显式bean扫描注释不兼容,比如@Componentscan

我建议任何对此感兴趣的人,阅读注释的完整javadoc(只有30行长,充满了浓缩的有用信息),但我会提取一些与我的情况相关的宝石。

来自注释类型WebMvcTest

使用此注释将禁用完全自动配置,而只应用与MVC测试相关的配置(即@Controller@ControllerAdvice@JsonComponent过滤器,WebMvcConfigurerHandlerMethodArgumentResolverbean,但不应用@Component@Service@Repositorybean)。[...] 如果您希望加载完整的应用程序配置并使用MockMVC,则应考虑将@SpringBootTest@AutoConfigureMockMvc结合使用,而不是使用此注释。

实际上,只有@SpringBootTest@AutoConfigureMockMvc解决了我的问题,所有其他使用@WebMvcTest的方法都无法加载一些所需的bean。

我收回我对Spring留档的评论,因为我没有意识到当使用@WebMvcTest时隐含了切片;实际上MVC切片留档明确表示并非所有应用程序都已加载,这是切片的本质。

带Spring靴1.4的定制测试片

测试切片是关于分割为测试创建的ApplicationContext。通常,如果你想用MockMvc测试一个控制器,你肯定不想麻烦数据层。相反,您可能希望模拟控制器使用的服务,并验证所有与web相关的交互是否按预期工作。

 类似资料:
  • 我试图测试我的Spring MVC控制器,但我不断收到与Thymeleaf模板相关的错误。我真的不想在控制器测试中处理模板错误,因为这不是我真正感兴趣的。当模板不存在时让测试失败是可以的,但现在我收到了与根据错误代码找不到消息相关的错误。 当我运行应用程序时,这个问题不存在。我一直在尝试弄清楚如何设置测试环境来解决这个问题,但在那里我找不到任何有效的方法。现在,我只是真的想让控制器代码正常工作。

  • 我试图用netty 4.0.10.final创建一个零拷贝应用程序。我在切片方面有问题。下面是我的解码(有问题的)方法: 我的应用程序/netty也可以接收不完整的消息。 在接收到整个消息时,整个管道处理工作良好。我的管道从ServerBootstrap开始->ChannelInitializer->ByteToMessageDecoder->ByteToMessageDecoder->Messa

  • 本文向大家介绍SpringMVC上传图片与访问,包括了SpringMVC上传图片与访问的使用技巧和注意事项,需要的朋友参考一下 关于springmvc上传图片的方法小编给大家整理了两种方法,具体内容如下所示: 第一种:(放在该项目下的物理地址对应的位置) a. 路径写法: String basePath="/WEB-INF/resources/upload"; String filePathNam

  • 我刚刚将一个应用程序从Spring Boot1.x迁移到2.1。我的一个测试由于bean重写默认值的更改而失败 我试图将设置为,但这不起作用。 您可以使用以下类再现此问题: 不及格的测试。Spring Boot2.1从不调用方法,而Spring Boot1.5或Spring Boot2.0则调用了它。

  • 问题内容: 我是Go编程的新手。我已经阅读了Go编程书籍,其中的内容由三部分组成:指向数组的指针,长度和容量。 我对nil slices(切片没有指向len的下层数组,len = 0,cap = 0),非lens切片(其中只有len = 0,cap = 0)和空切片之间感到困惑。 谁能告诉我nil和空片是否相同?如果两者都不相同,那么请说出两者之间的区别是什么? 如何测试切片是否为空? 另外,指针

  • 我是一个编程新手。我在go编程书中读到过,片由三部分组成:指向数组的指针、长度和容量。 我感到困惑的零切片(切片没有底层数组指向,len=0,cap=0),非零切片只有len=0,cap=0和空切片。 谁能告诉我零和空切片是否是一回事?如果它们都不同,那么请告诉这两者之间的区别是什么? 如何测试一个切片是否为空? 另外,指针在长度和容量为零的非nil片中保留什么值?