国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Springboot 如何使用Powermock做單元測試

這篇具有很好參考價(jià)值的文章主要介紹了Springboot 如何使用Powermock做單元測試。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Powermock介紹

一、為什么要使用Mock工具

在做單元測試的時(shí)候,我們會(huì)發(fā)現(xiàn)我們要測試的方法會(huì)引用很多外部依賴的對象,比如:(發(fā)送郵件,網(wǎng)絡(luò)通訊,遠(yuǎn)程服務(wù), 文件系統(tǒng)等等)。 而我們沒法控制這些外部依賴的對象,為了解決這個(gè)問題,我們就需要用到Mock工具來模擬這些外部依賴的對象,來完成單元測試。

二、PowerMock簡介

PowerMock 也是一個(gè)單元測試模擬框架,它是在其它單元測試模擬框架的基礎(chǔ)上做出的擴(kuò)展。通過提供定制的類加載器以及一些字節(jié)碼篡改技巧的應(yīng)用,PowerMock 現(xiàn)了對靜態(tài)方法、構(gòu)造方法、私有方法以及 Final 方法的模擬支持,對靜態(tài)初始化過程的移除等強(qiáng)大的功能。因?yàn)?PowerMock 在擴(kuò)展功能時(shí)完全采用和被擴(kuò)展的框架相同的 API, 熟悉 PowerMock 所支持的模擬框架的開發(fā)者會(huì)發(fā)現(xiàn) PowerMock 非常容易上手。PowerMock 的目的就是在當(dāng)前已經(jīng)被大家所熟悉的接口上通過添加極少的方法和注釋來實(shí)現(xiàn)額外的功能。
簡而言之,Powermock是mockito的升級(jí)版,但powermock會(huì)依賴于mockito。

使用示例

Maven 包引入

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <powermock.version>2.0.0</powermock.version>
</properties>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>

簡單使用

HelloMockitoTest

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)

//@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@PowerMockIgnore("javax.management.*")
@PrepareForTest({HelloController.class, TestUtils.class})
@ContextConfiguration(classes = TestBizServer.class)
@ActiveProfiles("local")
public class HelloMockitoTest {

    @InjectMocks
    private HelloController helloController;

    @Mock
    private HelloService helloService;

    @Before
    public void init () {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test () throws Exception {
        Mockito.when(helloService.sayHi(Mockito.any(String.class))).thenReturn("你好啊!");
        String result2 = helloController.testHello();
        System.out.println(result2);
        assert result2.equals("你好啊!");
    }

    @Mock
    private TestUtils testUtils;

    @Test
    public void testSome () throws Exception {
        TestUtils mock = Mockito.mock(TestUtils.class);
        PowerMockito.whenNew(TestUtils.class).withNoArguments().thenReturn(mock);
        Mockito.when(mock.testSome()).thenReturn("123456");
        String s = helloController.doHttpGet("http://127.0.0.1", Maps.newHashMap());
        System.out.println(s);
    }
}

HelloController 這里代碼都是偽代碼,不要把controller當(dāng)成一個(gè)rest,當(dāng)成一個(gè)Bean即可。

@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired(required = false)
    HelloService helloService;

    @GetMapping("/test")
    public String testHello () {
        String hello = null;
        try {
            Thread.sleep(1000);
            hello = helloService.sayHi("hello world");
            System.out.println("hello param is : " + hello);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return hello != null ? hello : "error";
    }

    @GetMapping("/testSome")
    public String doHttpGet(String uri, Map<String, String> getParams) {
        TestUtils testUtils = new TestUtils();
        String s = testUtils.testSome();
        System.out.println("testUtils.testSome return is:" + s);
        CloseableHttpResponse response = null;
        return s;
    }
}

HelloService

@Service
public class HelloService implements InitializingBean {

    @Autowired
    private HelloDao helloDao;

    public String sayHi () {
        System.out.println("HI ...");
        return "hi";
    }

    public String sayHi (String name) {
        System.out.println("HI ..." + name);
        return "hi";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("我是動(dòng)態(tài)注冊的你,不是容器啟動(dòng)的時(shí)候注冊的你");
    }

    public boolean deleteOne () {
        System.out.println("------------------------------");
        return helloDao.deleteOne();
    }
}

test方法運(yùn)行如果沒有寫mock正常會(huì)返回HI,這里會(huì)返回你好啊!。mockito這中mock方式只適用于Spring中注入代理的Bean才能進(jìn)行正常的mock。如果說這方法體中實(shí)例化了對象或者調(diào)用靜態(tài)方法,這個(gè)時(shí)候就不起作用了。

testSome中使用了powermock去處理在方法中實(shí)例化的新對象,把new對象替換為mock對象(可以理解為一層代理 ),然后讓調(diào)用mock對象的方法返回我們想要的值。

其實(shí)這里可以理解,如果我們想讓某個(gè)對象的方法返回一個(gè)值或者拋出一個(gè)異常,我們就需要把這個(gè)對象替換成mock對象,可以把mock對象理解為代理對象(打樁),這個(gè)是核心思路。

注解講解

@RunWith

在測試類類名上添加 @RunWith(PowerMockRunner.class) 注解代表該測試類使用 PowerMock。必須添加

@PrepareForTest

這個(gè)注解的作用就是告訴 PowerMock 哪些類是需要在字節(jié)碼級(jí)別上進(jìn)行操作的。也就是需要 mock 某些包含 final、static 等方法的類時(shí)使用,使用方法:@PrepareForTest({System.class, LogUtils.class}),在方法中有new對象的時(shí)候也需要在@PrepareForTest中聲明。

@PowerMockIgnore

PowerMock 是使用自定義的類加載器來加載被修改過的類,從而達(dá)到打樁的目的。@PowerMockIgnore 注解告訴 PowerMock 忽略哪些包下的類,從而消除類加載器引入的 ClassCastException。使用方法:@PowerMockIgnore({“javax.management.”, “javax.net.ssl.”, “javax.script.*”})

@SuppressStaticInitializationFor

告訴 PowerMock 哪些包下的類需要被抑制靜態(tài)初始化,包括 static 代碼塊或者 static 變量的初始化。防止因靜態(tài)初始化導(dǎo)致的錯(cuò)誤。使用方法:

@SuppressStaticInitializationFor({com.xxx.SmsServiceImpl})

@Mock
mock 待測類的普通屬性,最常見的就是通過 Spring @Autowired 自動(dòng)注入的 bean。這類屬性并非 final,也并非 static,只需要在測試類中使用 @Mock 注解,Pwermock 框架就能自動(dòng)生成 mock 對象,并自動(dòng)注入到 @InjectMock 修飾的待測類中。

也可以使用比較通用的 mock() 方法,調(diào)用 mock(XXX.class),能生成一個(gè) mock 的 XXX 對象,然后通過反射獲取待測類的字段,再將 mock 對象賦給字段。一般用于不是由 Spring @Autowired 注入的普通屬性。

PowerMock簡單實(shí)現(xiàn)原理

1.當(dāng)某個(gè)測試方法被注解@PrepareForTest標(biāo)注以后,在運(yùn)行測試用例時(shí),會(huì)創(chuàng)建一個(gè)新的org.powermock.core.classloader.MockClassLoader實(shí)例,然后加載該測試用例使用到的類(系統(tǒng)類除外)。

2.PowerMock會(huì)根據(jù)你的mock要求,去修改寫在注解@PrepareForTest里的class文件(當(dāng)前測試類會(huì)自動(dòng)加入注解中),以滿足特殊的mock需求。例如:去除’final方法的final標(biāo)識(shí),在靜態(tài)方法的最前面加入自己的虛擬實(shí)現(xiàn)等。

3.如果需要mock的是系統(tǒng)類的final方法和靜態(tài)方法,PowerMock不會(huì)直接修改系統(tǒng)類的class文件,而是修改調(diào)用系統(tǒng)類的class文件,以滿足mock需求。

Api講解

whenNew 當(dāng)創(chuàng)建新對象的時(shí)候

PowerMockito.whenNew(Entity.class).withAnyArguments().thenReturn(entity);

thenThrow 拋出異常
when 當(dāng)執(zhí)行xx方法的時(shí)候,一般后面跟鏈?zhǔn)秸{(diào)用處理分支
doNothing 什么都不執(zhí)行的時(shí)候,一般后面跟鏈?zhǔn)秸{(diào)用處理分支
doReturn 返回,一般后面接when(object).xxxMethod(), 意指讓mock對象調(diào)用某些方法的時(shí)候不做任何處理。

PowerMockito.doNothing().when(userMappers).putUser(Mockito.any(UserDTO.class));  //主要代碼

thenReturn 然后返回
mock 創(chuàng)建mock對象
mockStatic mock靜態(tài)class方法屬性,要在類前@PrepareForTest中加入使用SendEmailProxy的類。

PowerMockito.mockStatic(SendEmailProxy.class);
PowerMockito.when(SendEmailProxy.doSomething()).thenReturn(xxx);

any 模擬參數(shù)

PowerMockito.any(xxx.class)

注意

  • 如果項(xiàng)目中增加了springboot-actuator包則需要在類前加下述注解配置
@PowerMockIgnore({"javax.management.*"})
  • 如果需要測試HttpComponent包則需要在類前加下述注解配置
@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})

Powermock與Jacoco兼容問題

如果在@PrepareForTest中修飾了一個(gè)類,這個(gè)類jacoco就沒法進(jìn)行覆蓋率統(tǒng)計(jì)了,powermock是與jacoco的on-the-fly模式?jīng)_突的,但是有辦法可以避免這樣的問題。

原因

JaCoCo和PowerMock都是通過在加載類的時(shí)候修改字節(jié)碼文件來實(shí)現(xiàn)統(tǒng)計(jì)覆蓋率和mock靜態(tài)類的功能。JaCoCo在加載class的時(shí)候會(huì)把統(tǒng)計(jì)代碼插入到class中,而PowerMock當(dāng)使用了@PrepareForTest注解,在加載相關(guān)類的時(shí)候會(huì)從class文件重新讀取字節(jié)碼信息,導(dǎo)致JaCoCo的修改都沒有了,所以就沒辦法統(tǒng)計(jì)到了

on-the-fly模式的解決方案

1.不是用@PrepareForTest修飾要測覆蓋率的類,往需要覆蓋的類底層去mock,比如 A 依賴 B ,B依賴C,C依賴D。加入我們需要得到A和B的覆蓋率,那么我們在@PrepareForTest中就只添加C和D,只去mock C和D即可。
2.上述例子,假如我們A沒有依賴,但A中有成員變量需要mock,這個(gè)時(shí)候我們可以利用反射將成員變量設(shè)置為mock對象。然后再進(jìn)行mock操作,這樣就避免了再@PrepareForTest中加入A.class導(dǎo)致覆蓋率為零。

缺點(diǎn):
1.這樣寫對開發(fā)人員的要求比較高,要熟悉各種類庫(JDK、各種中間件),往代碼深處去mock代理取代在需要單元測試覆蓋率的類中進(jìn)行代理測試。
2.有些底層類不支持mock,比如Charset 的靜態(tài)方法中要求encode參數(shù)必須不能為空,powermock就沒法代理到Charset.encode的調(diào)用。

offline解決方案

使用jacoco的offline模式:

<!--- 定義 jacoco 版本 -->
<properties>
  <jacoco.version>0.8.5</jacoco.version>
</properties>
<!--- 定義 jacoco 執(zhí)行 offline 模式 goals -->
<build>
  <plugins>
    <!-- 注意不是在pluginManagement, pluginManagement中只是聲明 -->
    <plugin>
      <groupId>org.jacoco</groupId>
      <artifactId>jacoco-maven-plugin</artifactId>
      <version>${jacoco.version}</version>
      <executions>
        <execution>
          <id>default-instrument</id>
          <goals>
            <goal>instrument</goal>
          </goals>
        </execution>
        <execution>
          <id>default-restore-instrumented-classes</id>
          <goals>
            <goal>restore-instrumented-classes</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <!--離線模式必需指定, 否則到模塊根目錄而不是target目錄了-->
        <configuration>
            <systemPropertyVariables>
                <jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
            </systemPropertyVariables>
        </configuration>
    </plugin>
  </plugins>
</build>
<!--- 定義 jacoco 依賴  注意不是在dependencyManagement, dependencyManagement中只是聲明-->
<dependencies>
  <dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.agent</artifactId>
    <version>${jacoco.version}</version>
    <classifier>runtime</classifier>
  </dependency>
</dependencies>

Offline模式單元測試不能跨模塊, 不能源碼在A模塊單測寫在B模塊
比方說:項(xiàng)目分成了四個(gè)模塊,service,utils,dao,controller,你在寫service單測的時(shí)候哪怕調(diào)用了utils的代碼,但是在實(shí)際統(tǒng)計(jì)覆蓋率的時(shí)候是沒辦法統(tǒng)計(jì)到的,需要單獨(dú)針對每一個(gè)模塊寫單測文章來源地址http://www.zghlxwxcb.cn/news/detail-628395.html

到了這里,關(guān)于Springboot 如何使用Powermock做單元測試的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • java & jacoco & powerMock 單元測試覆蓋率為0怎么解決

    我們項(xiàng)目中使用powerMock作為單元測試的mock工具,統(tǒng)計(jì)項(xiàng)目測試覆蓋率使用jacoco編譯的結(jié)果上傳到sonar,但是jacoco 和 powerMock在運(yùn)行時(shí)runtime加載代碼的時(shí)候自定義了類加載器,所以就會(huì)有沖突,導(dǎo)致測試覆蓋率為0。 使用命令 mvn clean verify sonar:sonar上傳jacoco編譯結(jié)果(這里sonar命令

    2023年04月08日
    瀏覽(26)
  • 基于Junit4+Mockito+PowerMock實(shí)現(xiàn)Controller+Service的單元測試

    基于Junit4+Mockito+PowerMock實(shí)現(xiàn)Controller+Service的單元測試

    一 導(dǎo)入的依賴 二 依賴版本 三 controller測試示例代碼 ? ? ? controller ? ? ? ? controllerTest ? ? ? ? 測試結(jié)果:覆蓋率100% ? ? ? ? 帶異常的Controller ? ? ? ? 帶異常提示的ControllerTest ? ? ? ? 測試結(jié)果,覆蓋率100% ? 三 service測試示例代碼 ? ? ? ? service ? ? ? ? serviceTest ???

    2024年02月14日
    瀏覽(28)
  • PowerMock的簡單使用

    官方文檔:https://github.com/powermock/powermock/wiki 在做ut時(shí),發(fā)現(xiàn)要測試的方法會(huì)引用很多外部依賴的對象,就可能需要用Mock工具來模擬這些外部依賴的對象,來完成ut。 在EasyMock、Mockito等的基礎(chǔ)上,增加了對static、final、private等方法的mock。 1、引入依賴 版本可根據(jù)具體情況而定

    2024年02月14日
    瀏覽(19)
  • PowerMock使用-依賴準(zhǔn)備

    PowerMock 是一個(gè)單元測試框架,可以模擬靜態(tài)方法,私有方法和 final 方法等來簡化單元測試的編寫。本篇文章將對使用 PowerMock 需要的依賴進(jìn)行介紹。 一. 注解添加與使用場景 在使用 PowerMock 時(shí)需要針對不同場景添加對應(yīng)注解,主要是 @RunWith 和 @PrepareForTest 注解。注解添加和場

    2024年02月08日
    瀏覽(11)
  • PowerMock使用-Mock私有方法

    本篇文章將說明如何使用 PowerMock 對私有方法進(jìn)行 Mock 。關(guān)于使用 PowerMock 需要引入哪些依賴,請參考PowerMock使用-依賴準(zhǔn)備。 被測試類如下所示。 被測試類中有一個(gè)公共方法 isTrue() ,在 isTrue() 方法中會(huì)調(diào)用 MockPrivateMethod 的私有方法 returnTrue() 。測試類如下所示。 Mock 私有方

    2024年02月11日
    瀏覽(15)
  • PowerMock使用-Spy公共方法

    本篇文章將說明如何使用 PowerMock 對公共方法進(jìn)行 Spy 。關(guān)于使用 PowerMock 需要引入哪些依賴,請參考PowerMock使用-依賴準(zhǔn)備。 先給出一個(gè)示例,再對 Spy 進(jìn)行解釋。被測試類如下所示。 測試類如下所示。 Spy 公共方法時(shí)需要使用 PowerMockito.spy(方法所在類的實(shí)例) 獲取 Spy 出來的

    2024年02月05日
    瀏覽(14)
  • PowerMock使用-Mock靜態(tài)私有方法

    本篇文章將說明如何使用 PowerMock 對靜態(tài)私有方法進(jìn)行 Mock 。關(guān)于使用 PowerMock 需要引入哪些依賴,請參考PowerMock使用-依賴準(zhǔn)備。 被測試類如下所示。 被測試類中有一個(gè)靜態(tài)公共方法 isTrue() ,在 isTrue() 方法中會(huì)調(diào)用 MockStaticPrivateMethod 的靜態(tài)私有方法 returnTrue() 。測試程序如

    2024年02月14日
    瀏覽(18)
  • 如何做SpringBoot單元測試?

    如何做SpringBoot單元測試?

    單元測試(unit testing),是指對項(xiàng)目中的最?可測試單元進(jìn)?檢查和驗(yàn)證的過程就叫單元測試,對于Java來說或者是在SpringBoot項(xiàng)目中,最小的可測試單元就是一個(gè)方法。做單元測試就是為了證明某段代碼的執(zhí)?結(jié)果是否符合我們的預(yù)期。 1、可以?常簡單、直觀、快速的測試某

    2024年01月16日
    瀏覽(20)
  • SpringBoot如何寫好單元測試

    SpringBoot如何寫好單元測試

    Spring中的單元測試非常方便,可以很方便地對Spring Bean進(jìn)行測試,包括Controller、Service和Repository等Spring Bean進(jìn)行測試,確保它們的功能正常,并且不會(huì)因?yàn)閼?yīng)用的其他變化而出現(xiàn)問題。 1. 導(dǎo)入所需的依賴 :在測試類中,需要導(dǎo)入Spring Test相關(guān)的依賴,例如spring-test和JUnit。 2.

    2024年03月23日
    瀏覽(17)
  • SpringBoot 中如何利用 Junit 實(shí)現(xiàn)單元測試?

    SpringBoot 中如何利用 Junit 實(shí)現(xiàn)單元測試?

    2024軟件測試面試刷題,這個(gè)小程序(永久刷題),靠它快速找到工作了?。ㄋ㈩}APP的天花板)_軟件測試刷題小程序-CSDN博客 文章瀏覽閱讀2.5k次,點(diǎn)贊85次,收藏11次。你知不知道有這么一個(gè)軟件測試面試的刷題小程序。里面包含了面試常問的軟件測試基礎(chǔ)題,web自動(dòng)化測試、

    2024年03月11日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包