Spring 之 @ComponentScan以及mock Spring MVC

时间:2023-03-09 01:04:18
Spring 之 @ComponentScan以及mock Spring MVC

【 @ComponentScan】

纠正:可以成功 Autowired 的原因是我在另外一个 config 文件中扫描了根包,这会顺带扫描所有该包的子包

Spring 之 @ComponentScan以及mock Spring MVC

还有,,上面的写法容易出错,建议这样写,

@ComponentScan(basePackageClasses={Spittle.class},

效果上是完全等价的,只不过不再需要自己写字符串了, Spittle 是根包下的类。

----------------------------------------------------------------------------------------------------------------------------------------

原文(错):发现一件奇怪的事情,我明明没有指定扫描那个包,却能 Autowired 那个包中的类的对象不出现异常。

按理来说,要自动装配某一个类的对象,首先,需要在那个类上标注 @Component 或者是 @Controller ;其次,需要扫描那个类所在的那个包。我的情况是条件二并不满足却获得了那个对象。我尝试给那个类去掉 @Component 注释,结果报错了,所以并不是条件一有问题,明显是由于 Spring 自主扫描了我没有显式指定的那个包,并为那个带有组件声明的类创建了对象。

更加显式地指定要扫描的那个包:

@ComponentScan(basePackageClasses={HomeController.class})

结果仍然是不报错地获得了我没有显式指定扫描的那个包的类的对象,实验之后发现,成功自动装配的条件应该是:

  1. 在类的上面有相应的组件声明,例如 @Component 或者是 @Controller ,或者其它等价注释。
  2. 类所在的包被直接显式指定扫描,或者该类被直接显示指定扫描的那个(些)包中的类所 import

总之不管怎样,作为组件的声明都是必须的。

【 mock Spring MVC 】

基于使用概率导入大量的依赖包有个缺点就是一旦依赖包出现问题很难锁定问题到底出在哪里!!!

这些问题通常是由于依赖包的版本造成的 ( ╯□╰ ) , 因此对于依赖包的导入务必保证不必要不导入,并添加一些适当的注释

最好是能够清楚地了解各个包的用途、来源,这样也方便查相应的文档:

【pom.xml 模板】

标记为红色的是进行 mock 测试可能用到的包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>spittr</groupId>
<artifactId>spittr</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build> <dependencies>
<!-- spring-web 包括 web 、 bean 、aop 、 context 、 core 等 spring-webmvc 的子集-->
<!-- <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.9.RELEASE</version>
</dependency> --> <!-- jSTL taglibs-->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-spec</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency> <!-- spring-web 包括 web 、 bean 、aop 、 context 、 core、 webmvc 等 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency> <!-- spring-test 包括 test 等,含 mock -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.2.RELEASE</version>
<scope>test</scope>
</dependency> <!-- mock 相关的类库 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency> <!-- hamcrest 相关的类库 -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<!-- junit 包括 junit 、 hamcrest -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<!-- commons-lang 仅一个包,包括各种各样的工具,简化 hashCode 、 Equal 代码 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
</project>

【 mock Mvc】

package spittr.web;

import org.junit.Test;
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;
// 附上 API 文档地址: http://docs.spring.io/spring/docs/current/javadoc-api/
public class HomeControllerTest {
@Test
public void testHomePage() throws Exception {
HomeController controller = new HomeController();
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
mockMvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.view().name("home"));
}
}

可以修改为静态导入:

package spittr.web;

import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
// 附上 API 文档地址: http://docs.spring.io/spring/docs/current/javadoc-api/
public class HomeControllerTest {
@Test
public void testHomePage() throws Exception {
HomeController controller = new HomeController();
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
mockMvc.perform(get("/")).andExpect(view().name("home"));
}
}

 【 mock 一个接口的实现类】

package spittr.web;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.servlet.view.InternalResourceView; import spittr.Spittle;
import spittr.data.SpittleRepository; public class SpittleControllerTest {
@Test
public void shouldShowRecentSpittles() throws Exception {
List<Spittle> expectedSpittles = createSpittleList(20);
SpittleRepository mockRepository = mock(SpittleRepository.class);
when(mockRepository.findSpittles(Long.MAX_VALUE, 20)).thenReturn(expectedSpittles);
SpittleController controller = new SpittleController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller).setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp")).build();
mockMvc.perform(get("/spittles")).andExpect(view().name("spittles")).andExpect(model().attributeExists("spittleList"));
} public List<Spittle> createSpittleList(int count) {
List<Spittle> spittles = new ArrayList<>();
for (int i = 0; i < count; ++i) {
spittles.add(new Spittle("Spittle" + i, new Date()));
}
return spittles;
}
}