junit使用mock objects进行单元测试

版权声明:凭栏处,潇潇雨歇。 https://blog.csdn.net/IndexMan/article/details/85205597

上一篇我介绍了使用stub进行单元测试。那么mock objects和stub有何区别?什么情况下使用mock objects呢?

下面摘自junit in action书中的解释:

mock objects (或者简称为 mocks),非常适用于将某一部分代码与其他代问隔离开来,并对这部分代码进行测试。

mocks 替换了测试中与你的方法协作的对象,从而提供个隔离层。从这一点来讲,它与 stub 有些类似。不过相似之处也仅限于

此,因为mocks 并不实现任何逻辑 它们只是提供了一种使测试能够控制仿造类的所有业务逻辑方法行为的方法的空壳。

下面以一个账户转账的测试用例加以说明。大家可以比较下其与stub的区别。

创建账户类

package com.lhy.junitkaifa.mocks.account;

/**
 * 账户
 *
 * @author xusucheng
 * @create 2018-12-22
 **/
public class Account {
    private String accountId;
    private long balance;

    public Account(String accountId, long balance){
        this.accountId = accountId;
        this.balance = balance;
    }

    public void debit(long amount){
        this.balance-=amount;
    }

    public void credit(long amount){
        this.balance+=amount;
    }

    public long getBalance(){
        return this.balance;
    }
}

创建配置接口与实现

package com.lhy.junitkaifa.mocks.configurations;

/**
 * 配置
 *
 * @author xusucheng
 * @create 2018-12-22
 **/
public interface Configuration {
    String getSQL(String sqlString);
}
package com.lhy.junitkaifa.mocks.configurations;

/**
 * @author xusucheng
 * @create 2018-12-22
 **/
public class DefaultConfiguration implements Configuration {
    public DefaultConfiguration(String configuration){

    }

    @Override
    public String getSQL(String sqlString) {
        return null;
    }
}

 

创建账户管理接口与实现

package com.lhy.junitkaifa.mocks.account;

/**
 * 账户管理接口
 *
 * @author xusucheng
 * @create 2018-12-22
 **/
public interface AccountManager {
    Account findAccountById(String userId);

    void updateAccount(Account account);
}
package com.lhy.junitkaifa.mocks.account;

import com.lhy.junitkaifa.mocks.configurations.Configuration;
import com.lhy.junitkaifa.mocks.configurations.DefaultConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 账户管理接口实现
 *
 * @author xusucheng
 * @create 2018-12-22
 **/
public class AccountManagerImpl implements AccountManager {
    private Log logger;

    private Configuration configuration;

    public AccountManagerImpl(){
        this(LogFactory.getLog(AccountManagerImpl.class),new DefaultConfiguration("technical"));
    }

    public AccountManagerImpl(Log logger, Configuration configuration){
        this.logger = logger;
        this.configuration = configuration;
    }

    @Override
    public Account findAccountById(String userId) {
        this.logger.debug("Getting account for user["+userId+"]");
        this.configuration.getSQL("FIND_ACCOUNT_BY_ID");

        return null;
    }

    @Override
    public void updateAccount(Account account) {
        //Do nothing.
    }


}

创建账户管理服务类

package com.lhy.junitkaifa.mocks.account;

/**
 * 账户管理服务
 *
 * @author xusucheng
 * @create 2018-12-22
 **/
public class AccountService {
    private AccountManager accountManager;

    /**
     * 注入具体实现
     * @param accountManager
     */
    public void setAccountManager(AccountManager accountManager){
        this.accountManager = accountManager;
    }

    public void transfer(String fromId, String toId, long amount){
        //转出账户
        Account from = this.accountManager.findAccountById(fromId);
        //转入账户
        Account to = this.accountManager.findAccountById(toId);
        from.debit(amount);
        to.credit(amount);
        this.accountManager.updateAccount(from);
        this.accountManager.updateAccount(to);
    }
}

 

创建测试用账户管理接口

package com.lhy.junitkaifa.mocks.account;

import java.util.HashMap;
import java.util.Map;

/**
 * @author xusucheng
 * @create 2018-12-22
 **/
public class MockAccountManager implements AccountManager{
    //保存所有账户
    private Map<String,Account> accounts = new HashMap<>();


    /**
     * 添加账户
     * @param userId
     * @param account
     */
    public void addAccount(String userId, Account account){
        this.accounts.put(userId,account);
    }


    /**
     * 获取账户
     * @param userId
     * @return
     */
    @Override
    public Account findAccountById(String userId) {
        return this.accounts.get(userId);
    }

    @Override
    public void updateAccount(Account account) {
        //不干事
    }
}

创建测试用日志类

package com.lhy.junitkaifa.mocks.account;

import org.apache.commons.logging.Log;

/**
 * @author xusucheng
 * @create 2018-12-22
 **/
public class MockLog implements Log {
    @Override
    public boolean isFatalEnabled() {
        return false;
    }

    @Override
    public boolean isErrorEnabled() {
        return false;
    }

    @Override
    public boolean isWarnEnabled() {
        return false;
    }

    @Override
    public boolean isInfoEnabled() {
        return false;
    }

    @Override
    public boolean isDebugEnabled() {
        return false;
    }

    @Override
    public boolean isTraceEnabled() {
        return false;
    }

    @Override
    public void fatal(Object o) {

    }

    @Override
    public void fatal(Object o, Throwable throwable) {

    }

    @Override
    public void error(Object o) {

    }

    @Override
    public void error(Object o, Throwable throwable) {

    }

    @Override
    public void warn(Object o) {

    }

    @Override
    public void warn(Object o, Throwable throwable) {

    }

    @Override
    public void info(Object o) {

    }

    @Override
    public void info(Object o, Throwable throwable) {

    }

    @Override
    public void debug(Object o) {

    }

    @Override
    public void debug(Object o, Throwable throwable) {

    }

    @Override
    public void trace(Object o) {

    }

    @Override
    public void trace(Object o, Throwable throwable) {

    }
}

 

创建测试用配置类

package com.lhy.junitkaifa.mocks.configurations;

/**
 * @author xusucheng
 * @create 2018-12-22
 **/
public class MockConfiguration implements Configuration {
    public void setSQL(String sqlString){

    }

    @Override
    public String getSQL(String sqlString) {
        return null;
    }
}

 

创建测试类

package com.lhy.junitkaifa.mocks.account;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
 * @author xusucheng
 * @create 2018-12-22
 **/
public class TestAccountService {
    @Test
    public void testTransferOk(){
        MockAccountManager mockAccountManager = new MockAccountManager();
        Account from = new Account("1",200);
        Account to = new Account("2",100);
        mockAccountManager.addAccount("1", from);
        mockAccountManager.addAccount("2", to);

        AccountService accountService = new AccountService();
        accountService.setAccountManager(mockAccountManager);
        accountService.transfer("1","2",50);

        assertEquals(150,from.getBalance());
        assertEquals(150,to.getBalance());
    }
}

 

运行测试

猜你喜欢

转载自blog.csdn.net/IndexMan/article/details/85205597