1. 程式人生 > >單元測試之初步使用篇(testng + jmockit + springboot)

單元測試之初步使用篇(testng + jmockit + springboot)

單元測試研究

(testng + jmockit + springboot)

環境配置可以參考最下面的參考資料,其中已經非常清晰了。這裡不再描述了

引入spring自動配置

  1. 利用spingTesting 直接使用@ContextConfiguration
//1.ContextConfiguration中注入所需要的類,由於UserServiceImpl中@Autowired了UserInfoDao、AccountDao、 OssConfig,所以都需要注入。
@ContextConfiguration(classes = {UserServiceImpl.class, UserInfoDaoImpl.class, 
AccountDaoImpl.class, OssConfig.class})
//2.需要繼承AbstractTestNGSpringContextTests類
public class UserServiceImplTest extends AbstractTestNGSpringContextTests { @Autowired private UserServiceImpl serviceInterface; @Test public void testSpringAutoConfig(){ Person abc = serviceInterface.getUserInfoByName("abc"); System.out.println(abc); } } //3. UserServiceImpl、UserInfoDaoImpl、AccountDaoImpl修飾@Component
  1. 利用配置類@Configuration結合@ContextConfiguration
    利用一個配置類config.java配置完依賴之後,利用
    @ContextConfiguration(classes = Config.class),其他操作和1一樣。
  2. 利用springBootTesting
@SpringBootTest(classes = {UserServiceImpl.class, UserInfoDaoImpl.class, 
AccountDaoImpl.class, OssConfig.class})
public class UserServiceImplTest
extends AbstractTestNGSpringContextTests {
@Autowired private UserServiceImpl serviceInterface; @Test public void testSpringAutoConfig(){ Person abc = serviceInterface.getUserInfoByName("abc"); System.out.println(abc); } }

其他和@ContextConfiguration一樣,springboottest也可以使用@Configuration方式
4. 可以使用@SpringBootConfiguration(沒有研究跳過)
5. 使用@ComponentScan掃描Bean,前面都是使用@SpringBootTest或@ContextConfiguration(classes = {….})裝配bran,還可以使用@ComponentScan去掃描指定路徑

@SpringBootTest
@ComponentScan(basePackages = "com.dullbird")
//其中使用@SpringBootTest(classes = {OssConfig.class})或者@ContextConfiguration總是獲取不到配置檔案的值,但是使用ComponentScan可以獲取到。
//OssConfig 類如下
@Component
@ConfigurationProperties(prefix = "oss")
public class OssConfig {
    private String endpoint;
    private String outEndpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String readPublicBucket;
    //省略get和set方法
}
  1. 使用@SpringBootApplication配置
@SpringBootTest
/**
 * 使用SpringBootTest和ContextConfiguration,載入配置檔案沒有值,增加ComponentScan掃描就有值
 */
@SpringBootApplication(scanBasePackages = "com.dullbird")

[email protected]會覆蓋之前的配置。

@SpringBootApplication(scanBasePackages = "com.dullbird")
@TestPropertySource(properties = {"oss.accessKeyId = aaaaaa"})

mock物件或方法基於jmockit

比如測試類A,類A注入了bean B和C,測試A的方法時,呼叫了B和C的方法。這樣就引入了很多變數,需要用mock的方式把B和C的方法表現mock掉。接下來有幾種場景。
示例程式碼:

//介面
public interface ServiceInterface {
    Person getUserInfoByName(String name);
}
public interface AccountDao {
    String getAccountTest(String name);
}
public interface UserInfoDao {
    Person getUserInfoByName(String name);
    String getTestWord(String context);
}
@Component
public class AccountDaoImpl implements AccountDao {
    @Override
    public String getAccountTest(String name) {
        return name;
    }
}
@Component
public class UserInfoDaoImpl implements UserInfoDao {
    @Override
    public Person getUserInfoByName(String name) {
        return new Person(name, "18");
    }

    @Override
    public String getTestWord(String context) {

        return context;
    }
}
@Component
public class UserServiceImpl implements ServiceInterface {
    public static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private UserInfoDao userInfoDao;
    @Autowired
    private OssConfig ossConfig;
    //需要測試的方法
    @Override
    public Person getUserInfoByName(String name) {
        logger.info("進入類UserServiceImpl,獲取的引數name={}", name);
        String testWord = userInfoDao.getTestWord(name);
        logger.info("====testWord======================={}", testWord);
        String accountTest = accountDao.getAccountTest(name);
        logger.info("===accountTest========================{}", accountTest);
        //可以忽略
        logger.info("===ossConfig========================{}", ossConfig.getAccessKeyId());
        return userInfoDao.getUserInfoByName(name);
    }
}
1.全部都不mock程式碼,僅僅注入
@SpringBootTest
@SpringBootApplication(scanBasePackages = "com.dullbird")
public class UserServiceImplTest extends AbstractTestNGSpringContextTests {
    @Autowired
    private UserServiceImpl serviceInterface;

    @Test
    public void testServiceInterface() throws Exception {
        Person abc = serviceInterface.getUserInfoByName("abc");
        System.out.println(abc);
    }

這裡寫圖片描述

2. mock部分內容,比如例子中,僅僅希望mock部分程式碼。比如僅mock類userInfoDao的getTestWord(String name )方法和accountDao.getAccountTest(String name)方法。
@SpringBootTest
@SpringBootApplication(scanBasePackages = "com.dullbird")
public class UserServiceImplTest extends AbstractTestNGSpringContextTests {
    //首先需要mock的物件需要注入,這裡要對比一個@Injectable註釋
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private UserInfoDao userInfoDao;
    @Autowired
    private UserServiceImpl serviceInterface;

    @Test
    public void testServiceInterface() throws Exception {
        //進行mock,需要注意傳入了引數userInfoDao,表示僅僅mock例項userInfoDao的getTestWord方法,可以看到userInfoDao.getUserInfoByName方法的表現還是原來的樣子。下面會介紹一下Expectations。
        new Expectations(userInfoDao){
            {
                userInfoDao.getTestWord(anyString);
                result = "userInfoDao mock result";
            }
        };
        new Expectations(accountDao){
            {
                accountDao.getAccountTest(anyString);
                result = "accountDaoImpl mock result ";
            }
        };
        Person abc = serviceInterface.getUserInfoByName("abc");
        System.out.println(abc);
    }
}

這裡寫圖片描述

如果使用@Injectable測試一下
    @Autowired
    @Injectable
    private UserInfoDao userInfoDao;

這裡寫圖片描述
說明了一種情況,如果使用@Injectable修飾例項,例項所有的方法都會返回預設值。比如:
Person getUserInfoByName(String name);
String getTestWord(String context);
兩個方法返回的都是null, 基本型別的返回0.如果其中方法被mock。會按照mock來表現。

Expectations使用
    //引數可以傳入a.class或者例項,如果傳入例項,那麼僅僅mock部分方法。如果傳入.class會mock所有方法
    new Expectations(){
        {
            a.getTest();
            result = null;
            times =1;//呼叫次數,僅呼叫一次
            a.test();
            result = "two";
            times =1;
            //如果使用了Expectations,那麼Expectations裡面mock的方法都需要呼叫,並且需要按照順序。按照當前例子,需要先呼叫a.getTest(),再呼叫a.test()。如果多呼叫或者少呼叫,就會報錯。如果需要mock方法,但是不一定呼叫,需要使用NonStrictExpectations,使用方法一樣。呼叫沒有嚴格要求。
        }
    }
@Tested標籤(概念沒有那麼理解)

JMockit會自動建立註解為“@Tested”的類物件,並將其做為被測試物件。“@Tested”標註的必須是實體,不能是介面。否則會報錯
比如上面例子中UserServiceImpl serviceInterface;就是我們需要的測試物件。

@SpringBootTest
@SpringBootApplication(scanBasePackages = "com.dullbird")
public class UserServiceImplTest extends AbstractTestNGSpringContextTests {
    @Injectable
    private AccountDao accountDao;
    @Injectable
    private UserInfoDao userInfoDao;
    //這裡雖然注入了ossConfig,但是由於@Injectable標籤。ossConfig的所有方法獲取的值都是null或者0
    @Autowired
    @Injectable
    private OssConfig ossConfig;
    /**
     *如果使用@Tested描述,那麼UserServiceImpl注入的物件都需要@Injectable,否則會報錯,官方有提到部分mock,但    是這裡我沒有嘗試成功
     */
    @Tested
    private UserServiceImpl serviceInterface;

    @Test
    public void testServiceInterface() throws Exception {
        new Expectations(){
            {
                userInfoDao.getTestWord(anyString);
                result = "userInfoDao mock result";
            }
        };
        new Expectations(){
            {
                accountDao.getAccountTest(anyString);
                result = "accountDaoImpl mock result ";
            }
        };

        Person abc = serviceInterface.getUserInfoByName("abc");
        System.out.println(abc);
        System.out.println(abc.getName());
        System.out.println(abc.getAge());

    }
}

這裡寫圖片描述

留下的問題

  1. 需要自己研究的是不同的mock的作用範圍,有的是類級別的,有的是用例級別的。這個還沒有具體整理處理。
  2. @Tested是否是必須的,使用場景。根據官方文件說明的部分mock我還沒有實現。

參考資料

相關推薦

單元測試初步使用(testng + jmockit + springboot)

單元測試研究 (testng + jmockit + springboot) 環境配置可以參考最下面的參考資料,其中已經非常清晰了。這裡不再描述了 引入spring自動配置 利用spingTesting 直接使用@ContextConfigurat

Java單元測試JUnit

JUnit4通過註解的方式來識別測試方法。目前主要註解有: @BeforeClass 全域性只會執行一次,而且是第一個執行,且必須為static void @Before 在測試方法執行之前執行,即初

補習系列-springboot 單元測試

try 精彩 一次 run rest spec ner hat ltm 目錄 目標 一、About 單元測試 二、About Junit 三、SpringBoot-單元測試 項目依賴 測試樣例 四、Mock測試 五、最後 目標 了解 單元測試的背景 了解如何 利用

談談單元測試(四):測試工具 TestNG

前言 上一篇文章《測試工具 JUnit 4》中提到了 JUnit 4,並對 JUnit 4 做了簡單的討論,這篇文章我們將要圍繞另一款測試工具討論 —— TestNG。其實,這篇文章應該寫在《測試工具 JUnit 3》之後,和《測試工具 JU

.net core 單元測試 JustMock第一

前面介紹了單元測試的框架NUnit,它可以很好的幫助我們建立測試,檢驗我們的程式碼是否正確。但這還不夠,有時候我們的業務比較重,會依賴其它的類。基於隔離測試的原則,我們不希望依賴的其它類影響到我們的測試目標。這時候Mock就顯得十分重要了。當然還有其它因素使得我們必須Mock物件,比如配置檔案,DB等。 提供

.net core 單元測試 JustMock第二

JustMock標記方法 上篇文章在舉例子的時候使用了returns的標記方法,JustMock還有很多標記方法: CallOriginal 跟Behaviors裡的CallOriginal差不多意思,被呼叫時執行原始的方法和屬性的實現。 DoNothing 忽略對方法或者屬性的呼叫。 DoInstead

單元測試Stub和Mock

下載 我們 並且 試用 sample 註入 mes oge new 單元測試之Stub和Mock FROM:http://www.cnblogs.com/TankXiao/archive/2012/03/06/2366073.html 在做單元測試的時候,我們會發現我

python + unittest 做單元測試學習筆記

stl unittest 例子 gin pre log script 有關 assert 單元測試在保證開發效率、可維護性和軟件質量等方面有很重要的地位,所謂的單元測試,就是對一個類,一個模塊或者一個函數進行正確性檢測的一種測試方式。 這裏主要是就應用 python + u

單元測試重要性

表單 曾經 mybatis 服務 request 第一個 完成 分離 能說 單元測試的重要性不言而喻,自我開發生涯以來,從很少註釋過過場場,到非常重視。 單元測試為什麽會讓人忽視呢? 通常情況像一些查詢或者增刪改之類,拿我來說,即便報錯我大概一掃,我就知道錯誤是什麽了,該如

python筆記24-unittest單元測試mock.patch

rom Coding int self. 錯誤 測試用例 方法 org auto 前言 上一篇python筆記23-unittest單元測試之mock對mock已經有初步的認識, 本篇繼續介紹mock裏面另一種實現方式,patch裝飾器的使用,patch() 作為函數裝飾器

軟件測試兵器——測試工具【轉】

電話 跨項目 spa studio 桌面應用 mar 設備 也有 gin 功能測試篇   功能測試,是軟件測試裏的入門級心法,自然也有與之相對應的兵器來發揮心法的最大功力。 1) 屠龍刀之QTP 屠龍刀是金庸小說裏排名第一的寶刀,重劍無鋒,無堅不摧。素有“武林至尊,寶刀屠

單元測試Mock(Moq)

inter 商品 void 簡單 calc 不用 準備 targe ted Mock翻譯為“嘲弄”,其實就是偽造一個對象用於測試。在單元測試中,被測試方法依賴於其他對象時,為了測試簡單一般“偽造”一個這個對象;這樣做的目的: 不用考慮依賴對象的復雜性(方便準備測試數據)

java單元測試如何實現非同步介面的測試案例

測試是軟體釋出的重要環節,單元測試在實際開發中是一種常用的測試方法,java單元測試主要用junit,最新是junit5,本人開發一般用junit4。因為單元測試能夠在軟體模組組合之前儘快發現問題,所以實際開發中投入產出比很高。實際使用難免會遇到非同步操作的介面測試,最常用的情景是別人家的SD

前端單元測試Jest

概述 關於前端單元測試的好處自不必說,基礎的介紹和知識可以參考之前的部落格連結:React Native單元測試。在軟體的測試領域,測試主要分為:單元測試、整合測試和功能測試。 單元測試:在計算機程式設計中,單元測試(英語:Unit Testing)又稱為模組測試, 是針對程式模組(軟體設計的最小單

spring boot單元測試druid NullPointException

最近在使用spring boot 對 Controller 進行單元測試時,發現 druid 竟然丟擲了空指標異常。原因是,使用了druid的監控,需要經過druid的 Filter 攔截器,但是spr

powermockito單元測試深入實踐

概述 由於最近工作需要, 在專案中要做單元測試, 以達到指定的測試用例覆蓋率指標。專案中我們引入的powermockito來編寫測試用例, JaCoCo來監控單元測試覆蓋率。關於框架的選擇, 網上討論mockito和powermockito孰優孰劣的文章眾多, 這裡就不多做闡述, 讀者如有興趣可自行了解。

phpunit 單元測試程式碼覆蓋率

最近團隊在不斷完善專案中的單元測試用例,會用到程式碼覆蓋率分析,本來以為 homestead 應該預設安裝了 xdebug ,所以使用 phpunit --coverage-html ./tests/codeCoverage 來生成 html 報告,但是執行後提示如下錯誤 Error: No

談談單元測試(三):測試工具 JUnit 4

前言 上一篇文章《測試工具 JUnit 3》簡單的討論了 JUnit 3 的使用以及內部的方法。這篇文章將會在 JUnit 3 的基礎上,討論一下 JUnit 4 的新特性。同時,與 JUnit 3 做一個簡單的對比。那麼,廢話就不多說了,直

談談單元測試(二):測試工具 JUnit 3

前言 上一篇文章《 為什麼要進行煩人的單元測試?》討論了一下現階段軟體開發中,程式設計師們測試情況的現狀。這篇文章中,我打算介紹一下單元測試的工具(外掛),並且推薦大家以後在開發中,真正的用上單元測試,用好單元測試。

談談單元測試(一):為什麼要進行煩人的單元測試

前言 最近,在網上看到過一個調查,調查的內容是“程式設計師在專案開發中編寫單元測試的情況”。當然,至於調查的結果,我想聰明的你已經可以猜到了。高達 58.3% 的比例,一般情況下不寫單元測試,只有偶爾的情況才會寫寫。16.6%