如何使用Junit / Mockito编写此费用计算器服务的测试用例?

时间:2018-09-27 10:02:49

标签: java junit mockito

我有这个服务类别-

package com.test.common.fee;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;

import javax.annotation.PostConstruct;

import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class FeeCalcService {

    @Value("${json.config.folder}")
    String jsonConfigFolder;

    FeeConfigEntity feeConfig = new FeeConfigEntity();

    @PostConstruct
    public void init() throws IOException {
        ObjectMapper jsonMapper = new ObjectMapper();
        File jsonFile = getFilesInFolder(jsonConfigFolder);

        // deserialize contents of each file into an object of type
        feeConfig = jsonMapper.readValue(jsonFile, FeeConfigEntity.class);
    }

    public BigDecimal calculateFee(BigDecimal amount)
    {
        String type = feeConfig.getType();
        Integer total = feeConfig.getDetails().size();
        BigDecimal fee = new BigDecimal(0);
        if(type.equals("slab"))
        {
            if(total>1)
            {
                for(FeeConfigDetailsEntity eachSlab : feeConfig.getDetails()){
                    BigDecimal min = BigDecimal.valueOf(eachSlab.getDetails().getMin());
                    BigDecimal max = BigDecimal.valueOf(eachSlab.getDetails().getMax());
                    if((amount.compareTo(min) == 1 || amount.compareTo(min) == 0)
                            &&
                        (amount.compareTo(max) == -1 || amount.compareTo(min) == 0)
                    )
                    {
                        float value = eachSlab.getDetails().getValue();
                        if(eachSlab.getDetails().getType().equals("flat"))
                        {
                            fee = BigDecimal.valueOf(value);
                        }
                        else if(eachSlab.getDetails().getType().equals("fixed"))
                        {
                            MathContext mc = new MathContext(4); // 4 precision
                            fee = amount.multiply(BigDecimal.valueOf(value), mc).divide(BigDecimal.valueOf(100), mc);
                        }
                        break;
                    }
                }
            }
        }
        else if(total>1)
        {
            //incorrect setup
        }
        else
        {//expected flat/fixed
            float value = feeConfig.getDetails().get(0).getDetails().getValue();

            if(type.equals("flat"))
            {
                fee = BigDecimal.valueOf(value);
            }
            else if(type.equals("fixed"))
            {
                MathContext mc = new MathContext(4); // 4 precision
                fee = amount.multiply(BigDecimal.valueOf(value), mc).divide(BigDecimal.valueOf(100), mc);
            }
        }

        return fee;
    }

    /*public List<ContextOperatorBean> getMatchingOperators(String context) {
        return operators.stream().filter(operator -> checkIfMatches(operator, context)).collect(Collectors.toList());
    }

    private boolean checkIfMatches(ContextOperatorBean operator, String context) {
        // TODO implement
        return false;
    }*/

    private File getFilesInFolder(String path) {
        // TODO implement   
        File test = new File(path);
        return test;
    }
}

init()函数将该结构的json文件加载到FeeConfigEntity类中-

{
    "type": "slab",
    "details": [{
            "slabName": "slab_1",
            "details": {
                "min": 0,
                "max": 100,
                "type": "fixed",
                "value": "12"
            }
        },
        {
            "slabName": "slab_2",
            "details": {
                "min": 101,
                "max": null,
                "type": "flat",
                "value": "100"
            }
        }
    ]
}

FeeConfigEntity类的结构-

package com.test.common.fee;

import java.util.List;

public class FeeConfigEntity {

    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public List<FeeConfigDetailsEntity> getDetails() {
        return details;
    }

    public void setDetails(List<FeeConfigDetailsEntity> details) {
        this.details = details;
    }

    private List<FeeConfigDetailsEntity> details;

    }

基本上,这是一项服务,返回的佣金/费用将根据json文件中定义的佣金结构适用于一定金额。

这就是我从应用程序中调用它的方式-

BigDecimal fee = feeCalcService.calculateFee(amount);

我对Junit测试非常陌生,但并不清楚应该如何做。

我的想法是-

  • 服务类结构中需要进行一些更改。
  • init函数不会返回任何内容,因此我无法在此处放置when()thenReturn(),否则我可能会用所需的内容覆盖这里。

2 个答案:

答案 0 :(得分:0)

FeeCalcService创建一个对象,并使用对象调用init()。然后使用相同的对象调用calculateFee,然后使用具有期望值的实际值进行验证。

答案 1 :(得分:0)

我认为FeeCalcService应该针对几个不同的FeeConfigEntity实体进行测试。

有多种实现方法,例如:

在您的课程中添加2个构造函数:

public FeeCalcService() {
}

FeeCalcService(FeeConfigEntity feeConfig) {
    this.feeConfig = feeConfig;
}

第二个仅用于测试。

然后编写一些这样的测试:

@Test
public void test1() {
    FeeConfigEntity config1 = new FeeConfigEntity();
    config1.setType(...);
    config1.setDetails(...);
    Assert.assertEquals(new BigDecimal(10), new FeeCalcService(config1).calculateFee(new BigDecimal(100)));
}

此处不需要Mockito。当处理的某些部分被委托到另一个类时,这特别有用,但是这里不是这种情况。