spring /spring boot中mock


1 Mockito簡介

1.1 Mockito是什么

  Mockito是一個簡單的流行的Mock框架。它允許你創建和配置mock對象。使用Mockito可以明顯的簡化對外部依賴的測試類的開發。一般使用 Mockito 需要執行下面三步: 
 模擬並替換測試代碼中外部依賴;
 執行測試代碼;
 驗證測試代碼是否被正確的執行。

1.2 Mock是什么

  Mock測試就是在測試過程中,對某些不容易構造或者不容易獲取的對象,用一個虛擬的Mock對象來創建以便測試的測試方法。
  Mock最大的功能是幫你把單元測試的耦合分解開,如果你的代碼對另一個類或者接口有依賴,它能夠幫你模擬這些依賴,並幫你驗證所調用的依賴的行為。

2 Mockito在Spring框架中的使用

2.1 依賴包

<dependency>
     <groupId>org.mockito</groupId>
     <artifactId>mockito-core</artifactId>
     <version> 2.21 . 0 </version>
     <scope>test</scope>
</dependency>

Mockito在Spring可以通過配置文件和注解的方式使用

2.2 通過xml配置文件使用Mockito

  Mockito創建方式有兩種:mock,spy。mock為一個interface提供一個虛擬的實現,spy為object加一個動態代理,實現部分方法的虛擬化,但是需要賦予一個instance。
  Mockito提供了factory的方法用來創建mock和spy。
  假設構造系統中有serviceA,serviceB,serviceC,其中serviceA依賴serviceB依賴serviceC。serviceC是最基本的。現在需要對其中serviceA進行測試,但其serviceC需要依賴於外部環境,而這個環境需要復雜而且不穩定的數據庫。這時需要mock或spy掉serviceC。

注:無論是spring框架還是spring boot框架,如果集成了MyBatis,因Mybatis中Mapper基於動態代理實現,則其對應的mapper接口只能基於xml文件配置方式注入mock或spy。
具體解釋參考:https://sq.163yun.com/blog/article/169561874192850944

第一步:在配置文件中注入mock:

<bean id= "serviceC"   class = "org.mockito.Mockito" factory-method= "mock" >
     <constructor-arg value= "com.x.y.x.ServiceC" ></constructor-arg>
</bean>

或注入spy

<bean id= "serviceCInst"   class = "serviceCInstance" >
</bean>
<bean id= "serviceC"   class = "org.mockito.Mockito"  factory-method= "spy" >
        <constructor-arg ref= "serviceCInst" ></constructor-arg>
</bean>

spy需要獲得一個實例。

第二步:

在測試用例中@Resource或@Autowired引入serviceC。

2.3 通過注解使用Mockito

以代碼舉例

@Component
public  class  OrderCreate {
 
     @Resource
     private  OrderHelper orderHelper;
 
     public  void  create() {
         System.out.println(getAmt());
         System.out.println(orderHelper.resolve());
     }
 
     public  int  getAmt() {
         return  10 ;
     }
}
@Component
public  class  OrderHelper {
     public  String  resolve() {
         return  "resolve order" ;
     }
}

測試類:

public  class  MockSpringTest {
 
     @InjectMocks
     private  OrderCreate orderCreate;
     
     @Mock
     private  OrderHelper orderHelper;  // 此mock將被注入到orderCreate
 
     @Before
     public  void  initMocks() throws Exception {
         MockitoAnnotations.initMocks( this );
     }
 
     @Test
     public  void  create() {
         System.out.println( "start mock..." );
         when(orderHelper.resolve()).thenReturn( "null" );
         orderCreate.create();
     }
}

運行結果:

start mock...
10
null

mock() / @Mock:創建一個mock;
spy() / @Spy:創建一個spy,提供了一種對真實對象操作的方法;
@InjectMocks:創建一個實例。被@Mock(或@Spy)注解創建的mock將被注入到用該實例中。注意: @InjectMocks標注的屬性不能使用接口。

3 Mockito在Spring boot 框架中的使用

3.1 Spring Boot自帶測試模塊

  Spring boot自身提供很多有用的工具類和注解用於測試應用,主要分兩個模塊:spring-boot-test包含核心組件,spring-boot-test-autoconfigure為測試提供自動配置。開發者只需要引用spring-boot-starter-test即可。它提供的測試模塊中包含了Mockito。
  Spring boot使用@MockBean和@SpyBean來定義Mockito的mock和spy。SpringBoot提供的@MockBean注解,用於為Applicatio nContext中的bean定義一個mock,你可以使用該注解添加新beans,或替換已存在的bean定義。該注解可直接用於測試類,也可用於測試類的字段,或用於@Configuration注解的類和字段。當用於字段時,創建mock的實例也會被注入。Mock beans每次調用完測試方法后會自動重置。

以代碼舉例:

@Component
public  class  MethodTest {
 
    public  String  One(boolean flag){
        System.err.println( "coming........." );
        String  d = Two(flag);
        Three();
        System.err.println( "result data is " +d);
        return  d;
    }
 
    public  String  Two(boolean flag){
        System.err.println( "coming.........two" );
        if (flag){
            throw  new  IllegalAccessError();
        }
        return  "two" ;
    }
 
    public  void  Three(){
        System.err.println( "coming.........three" );
    }
}

測試類 @SpyBean

@RunWith(SpringRunner. class )
@SpringBootTest(classes = DemoApplication. class )
public  class  SpyTest{
        @SpyBean
        private  MethodTest spyTest;
        @Test
        public  void  test3(){
            when(spyTest.Two( false )).thenReturn( "test" );
            System.err.println(spyTest.One( false ));
    }
}

運行結果:

coming.........two
coming.........
coming.........three
result data  is  test
test

測試類 @MockBean

@RunWith(SpringRunner. class )
@SpringBootTest(classes = DemoApplication. class )
public  class  MockTest{
    @MockBean
    private  MethodTest mockTest;
    @Test
    public  void  test3(){
        when(mockTest.One( false )).thenReturn( "test" );
        System.err.println(mockTest.One( false ));
    }
}

運行結果:

test

3.2 Spring Boot使用原生Mockito

       使用方式見第2部分。

4 總結

  為了統一springBoot和spring項目對Mockito的配置方式,同時解決框架中Mybaties之Mapper動態代理的mock場景,建議統一使用xml文件配置的方式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM