使用Spring Boot進行單元測試時,發現使用@Autowired注解的類無法自動注入,當使用這個類的實例的時候,報出NullPointerException,即空指針異常。
Spring Boot中的單元測試
先簡單說一下Spring Boot中的單元測試。
要在Spring Boot中使用單元測試是很簡單的,Spring Boot提供了spring-boot-starter-test的依賴,即JUnit的相關依賴。
在pom.xml文件中引入依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency>
單元測試的語法也很簡單,使用@Test注解在方法上或在類上就可以進行簡單的單元測試了。
public class yanggbTest { @Test public void test1 () { System.out.println("我是一個簡單測試。"); } }
自動注入servicei或dao報空指針異常的原因
說回在JUnit單元測試類中自動注入servicei或dao為什么會報空指針異常,報錯的原因很明顯是@Autowired自動注入注解沒有成功將類的實例注入。
我們知道,在Spring中,類的實例是交給容器管理的,而在測試類中,容器因為沒有相應的上下文環境,是沒有辦法找到相應的類並進行相應的初始化/實例化操作,因此也就沒有在測試類中成功注入類的實例,在試圖使用類的實例的情況下也就會報空指針異常的錯誤。
如何注入service或dao
根據上面的分析,如果要注入service或dao的話,我們需要給容器構建一個上下文環境,這里具體是Spring Boot的運行環境。
我們可以通過在測試類上添加兩個注解來實現構建上下文環境的效果。
@RunWith(SpringRunner.class) @SpringBootTest(classes = RenjApplication.class) public class yanggbTest { }
我們從注解的命名上就可以看出其功能,但這里還是簡單介紹一下。
@RunWith注解
@RunWith注解是類級別的注解, 它提供了一種更改測試運行程序的默認行為的機制。簡單理解,@RunWith注解就是一個運行器,其接受一個類的簽名來指定是使用什么類、在什么環境下運行。需要注意的是,該注解的參數必須是Runner類的子類,JUnit本身有提供幾個Runner,默認值為JUnit4,一個常見的替代方法是參數化類。
當使用@RunWith注解對JUnit測試進行注解時,將對測試的生命周期和測試的運行方式進行一些更改。
比如@RunWith(JUnit4.class)就是指用JUnit4來運行。
比如@RunWith(SpringJUnit4ClassRunner.class)就是讓測試運行於Spring測試環境。
比如@RunWith(Suite.class)的話就是一套測試集合。
比如@RunWith(SpringJUnit4ClassRunner.class)使用了Spring的SpringJUnit4ClassRunner,以便在測試開始的時候自動創建Spring的應用上下文。一般情況下想創建spring容器的話,需要通過web.xml配置classloder,但如果注解了@RunWith注解的話,就可以直接使用spring容器,直接使用@Test注解,不用啟動spring容器。
在上面的代碼中,使用了@RunWith(SpringRunner.class),實際上,SpringRunner類就是繼承於Spring的SpringJUnit4ClassRunner類。
@SpringBootTest注解
@SpringBootTest注解是一個Spring Boot提供的注解,通過這個注解可以使JUnit單元測試跑在Spring Boot的運行環境中。
我們可以通過classes參數來指定Spring Boot的啟動類。
完整的示例例
最后我們來看一個完整的、在測試類中注入service的示例。
@RunWith(SpringRunner.class) @SpringBootTest(classes = RenjApplication.class) public class yanggbTest { @Autowried RenjServiceImpl renjService; @Test public void test1 () { renjService.loveYanggb(); } }
這樣我們就能在測試類中愉快地調用service中的方法了,dao也是同樣的。
"成熟的標志不是會說大道理,而是開始去理解身邊的小事,去體諒周遭的不得已。"