51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 7268|回复: 0
打印 上一主题 下一主题

[原创] Java单元测试——Mock技术

[复制链接]
  • TA的每日心情
    无聊
    3 天前
  • 签到天数: 1050 天

    连续签到: 1 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2020-12-7 10:41:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    1测试积点
    1.源代码
      AccountService.java
    1.  package com.account;

    2.   import com.account.Account;

    3.   import com.account.AccountManager;

    4.   public class AccountService

    5.   {

    6.   //使用的帐户管理器实现

    7.       private AccountManager accountManager;

    8.       //设置帐户管理器实现的设置方法

    9.       public void setAccountManager( AccountManager manager )

    10.       {

    11.           this.accountManager = manager;

    12.       }

    13.       //一个设置客户经理实现从账户到账户的senderId beneficiaryId setter方法。

    14.       //senderId:转出方Id

    15.       //beneficiaryId:收益方Id

    16.       //amount:金额

    17.       public void transfer( String senderId, String beneficiaryId, long amount )

    18.       {

    19.           //初始化转出方与收益方,findAccountForUser为接口类方法

    20.       Account sender = this.accountManager.findAccountForUser( senderId );

    21.           Account beneficiary = this.accountManager.findAccountForUser( beneficiaryId );

    22.           //转入和收益

    23.           sender.debit( amount );

    24.           beneficiary.credit( amount );

    25.           //更新,updateAccount为接口类方法

    26.           this.accountManager.updateAccount( sender );

    27.           this.accountManager.updateAccount( beneficiary );

    28.       }

    29.   }
    复制代码
    Account.java
    1.  package com.account;

    2.   public class Account

    3.   {

    4.       private String accountId;

    5.       private long balance;

    6.       public Account(String accountId, long initialBalance)

    7.       {

    8.           this.accountId = accountId;

    9.           this.balance = initialBalance;

    10.       }

    11.       //借记

    12.       public void debit( long amount )

    13.       {

    14.           this.balance -= amount;

    15.       }

    16.       //信用

    17.       public void credit( long amount )

    18.       {

    19.           this.balance += amount;

    20.       }

    21.       public long getBalance()

    22.       {

    23.           return this.balance;

    24.       }

    25.   }
    复制代码
    AccountManager.java
    1.  package com.account;

    2.   import com.account.Account;

    3.   public interface AccountManager

    4.   {

    5.       Account findAccountForUser(String userId );

    6.       void updateAccount(Account account );   

    7.   }
    复制代码
    由于在这里AccountManager.java仅仅做了一个interface,我们主要Mock的是这个类。这几个类的类关系图如下:

     通常的调用方法如下:
    1. @Test

    2.   public void testTransferOK() {

    3.   Account sendAccount = new Account("1",200);

    4.   Account beneficiaryAccount = new Account("2",100);

    5.   AccountManager. updateAccount( senderAccount );

    6.   AccountManager.updateAccount( beneficiaryAccount );

    7.   AccountManager.findAccountForUser("1" )

    8.   AccountManager.findAccountForUser( "2" )

    9.   AccountService accountService = new AccountService();

    10.   accountService.setAccountManager(AccountManager);

    11.   accountService.transfer("1","2",50); //转钱

    12.   Assertions.assertEquals(150,sendAccount.getBalance());

    13.   Assertions.assertEquals(150,beneficiaryAccount.getBalance());

    14.   }
    复制代码
    2.最通用的Mock技术  StubAccountManager.java
    1. package com.account;

    2.   import java.util.HashMap;

    3.   public class StubAccountManager implements AccountManager{

    4.   private HashMap<String,Account> accounts = new HashMap<String,Account>();

    5.   public void addAcount(String userId,Account account){

    6.   this.accounts.put(userId,account);

    7.   }

    8.   

    9.   public Account findAccountForUser(String userId){

    10.   return this.accounts.get(userId);

    11.   }

    12.   

    13.   public void updateAccount(Account account){

    14.   //do nothing

    15.   }

    16.   }
    复制代码
    Account.java
    1. import static org.junit.Assert.assertEquals;

    2.   import org.junit.jupiter.api.Test;

    3.   public class TestAccountService {

    4.   @Test

    5.   public void testTransferOK() {

    6.   StubAccountManager stubAccountManager = new StubAccountManager(); //定义MockAccountManager类

    7.   Account sendAccount = new Account("1",200); //定义收钱方和出钱方两个Account

    8.   Account beneficiaryAccount = new Account("2",100);

    9.   stubAccountManager.addAcount("1", sendAccount); //初始化收钱方和出钱方HashMap

    10.   stubAccountManager.addAcount("2", beneficiaryAccount);

    11.   AccountService accountService = new AccountService(); //初始化AccountService类

    12.   accountService.setAccountManager(stubAccountManager); //初始化AccountManager

    13.   accountService.transfer("1","2",50); //转钱

    14.   Assertions.assertEquals(150,sendAccount.getBalance()); //判断转换后收付方金额是否正确

    15.   Assertions.assertEquals(150,beneficiaryAccount.getBalance());

    16.   }}
    复制代码
    3.EasyMock技术  EasyMock需要以下两个jar包:easymock-2.4.jar和easymockclassextension-2.4.jar
      TestAccountServiceEasyMock.java
    1. package com.account;

    2.   import static org.easymock.EasyMock.createMock;

    3.   import static org.easymock.EasyMock.replay;

    4.   import static org.easymock.EasyMock.expect;

    5.   import static org.easymock.EasyMock.verify;

    6.   import org.junit.jupiter.api.BeforeEach;

    7.   import org.junit.jupiter.api.AfterEach;

    8.   import org.junit.jupiter.api.Assertions;

    9.   import org.junit.jupiter.api.DisplayName;

    10.   import org.junit.jupiter.api.Test;

    11.   import com.account.Account;

    12.   import com.account.AccountManager;

    13.   import com.account.AccountService;

    14.   public class TestAccountServiceEasyMock {

    15.   private AccountManager mockAccountManager;

    16.       @BeforeEach

    17.       public void setUp()

    18.       {

    19.           //初始化easyMock

    20.       mockAccountManager = createMock("mockAccountManager", AccountManager.class );

    21.       }

    22.       @Test

    23.       @DisplayName("测试转账")

    24.       public void testTransferOk()

    25.       {

    26.           Account senderAccount = new Account( "1", 200 );

    27.           Account beneficiaryAccount = new Account( "2", 100 );

    28.           

    29.           //开始定义期望

    30.           mockAccountManager.updateAccount( senderAccount );

    31.           mockAccountManager.updateAccount( beneficiaryAccount );

    32.           //EasyMock的expect和replay方法

    33.           expect( mockAccountManager.findAccountForUser( "1" ) ).andReturn( senderAccount ); //期望返回senderAccount

    34.           expect( mockAccountManager.findAccountForUser( "2" ) ).andReturn( beneficiaryAccount ); //期望返beneficiaryAccount

    35.           replay( mockAccountManager );//切换到replay状态 Record-> replay,在replay状态才可以进行验证

    36.           AccountService accountService = new AccountService();

    37.           accountService.setAccountManager( mockAccountManager );

    38.           accountService.transfer( "1", "2", 50 );

    39.           Assertions.assertEquals( 150, senderAccount.getBalance() );

    40.           Assertions.assertEquals( 150, beneficiaryAccount.getBalance() );

    41.       }

    42.       @AfterEach

    43.       public void tearDown()

    44.       {

    45.           verify( mockAccountManager );

    46.       }

    47.   }
    复制代码
    4. JMock技术  JMock依赖下面11个jar包。另外JMock不完全兼容JUnit5

     TestAccountServiceJMock.java
    1. package com.account;

    2.   import org.jmock.integration.junit4.JMock;

    3.   import org.jmock.integration.junit4.JUnit4Mockery;

    4.   import org.jmock.Expectations;

    5.   import org.jmock.Mockery;

    6.   import org.junit.jupiter.api.Assertions;

    7.   import org.junit.jupiter.api.BeforeEach;

    8.   import org.junit.jupiter.api.DisplayName;

    9.   import org.junit.jupiter.api.Test;

    10.   import org.junit.runner.RunWith;

    11.   import com.account.Account;

    12.   import com.account.AccountManager;

    13.   import com.account.AccountService;

    14.   @RunWith(JMock.class)

    15.   public class TestAccountServiceJMock {

    16.   /**

    17.        * The mockery context that we use to create our mocks.

    18.        */

    19.       private Mockery context = new JUnit4Mockery();

    20.       /**

    21.        * The mock instance of the AccountManager to use.

    22.        */

    23.       private AccountManager mockAccountManager;

    24.   @BeforeEach

    25.   public void setUp(){

    26.    mockAccountManager = context.mock( AccountManager.class );

    27.   }

    28.   @Test

    29.   @DisplayName("测试转账")

    30.       public void testTransferOk()

    31.       {

    32.           final Account senderAccount = new Account( "1", 200 );

    33.           final Account beneficiaryAccount = new Account( "2", 100 );

    34.           context.checking( new Expectations()

    35.           {

    36.               {

    37.                   oneOf( mockAccountManager ).findAccountForUser( "1" );

    38.                   will( returnValue( senderAccount ) );

    39.                   oneOf( mockAccountManager ).findAccountForUser( "2" );

    40.                   will( returnValue( beneficiaryAccount ) );

    41.                   oneOf( mockAccountManager ).updateAccount( senderAccount );

    42.                   oneOf( mockAccountManager ).updateAccount( beneficiaryAccount );

    43.               }

    44.           } );

    45.           AccountService accountService = new AccountService();

    46.           accountService.setAccountManager( mockAccountManager );

    47.           accountService.transfer( "1", "2", 50 );

    48.           Assertions.assertEquals( 150, senderAccount.getBalance() );

    49.           Assertions.assertEquals( 150, beneficiaryAccount.getBalance() );

    50.       }  

    51.   }
    复制代码
    4.1 One,one of  JMock2.4版以前:one;
      JMock2.51版以后:one of。
    1. oneOf (anObject).doSomething(); will(returnValue(10));

    2.   oneOf (anObject).doSomething(); will(returnValue(20));

    3.   oneOf (anObject).doSomething(); will(returnValue(30));
    复制代码
     第一次调用时会返回10,第二次会返回20,第三次会返回30。  4.2 atLeast(n).of
    1.  atLeast(1).of (anObject).doSomething();  

    2.   will(onConsecutiveCalls( returnValue(10),  returnValue(20),  returnValue(30)));
    复制代码
     这里atLeast (1)表明doSomething方法将至少被调用一次,但不超过3次。且调用的返回值分别是10、20、30.

    5. mockito技术  需要mockito-all-1.9.5.jar包。
    1.  package com.account;

    2.   import static org.mockito.Mockito.*;

    3.   import org.junit.jupiter.api.Assertions;

    4.   import org.junit.jupiter.api.BeforeEach;

    5.   import org.junit.jupiter.api.DisplayName;

    6.   import org.junit.jupiter.api.Test;

    7.   import org.mockito.Mockito;

    8.   import com.account.Account;

    9.   import com.account.AccountManager;

    10.   import com.account.AccountService;

    11.   public class TestAccountServiceMockito {

    12.   private AccountManager mockAccountManager;

    13.   private Account senderAccount;

    14.   private Account beneficiaryAccount;

    15.   @BeforeEach

    16.   public void setUp(){

    17.   mockAccountManager = Mockito.mock(AccountManager.class);

    18.   

    19.   senderAccount = new Account( "1", 200 );

    20.           beneficiaryAccount = new Account( "2", 100 );

    21.           

    22.           mockAccountManager.updateAccount( senderAccount );

    23.           mockAccountManager.updateAccount( beneficiaryAccount );

    24.           

    25.           when(mockAccountManager.findAccountForUser("1")).thenReturn( senderAccount );

    26.           when(mockAccountManager.findAccountForUser("2")).thenReturn( beneficiaryAccount );

    27.   }

    28.   

    29.   @Test

    30.   @DisplayName("测试转账")

    31.   public void test() {

    32.           AccountService accountService = new AccountService();

    33.           accountService.setAccountManager( mockAccountManager );

    34.           accountService.transfer( "1", "2", 50 );

    35.           Assertions.assertEquals( 150, senderAccount.getBalance() );

    36.           Assertions.assertEquals( 150, beneficiaryAccount.getBalance() );

    37.   }

    38.   }
    复制代码

















    附件: 您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-24 06:44 , Processed in 0.067088 second(s), 22 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表