在抽象类中模拟一个新的Object实例

时间:2015-12-21 16:02:54

标签: java junit mockito

我有一个AbstractDao类,我在其中实例化Rest Fore API。我无法在Power Mock中模拟新的forceAPI(config)。请建议。

@RunWith(BlockJUnit4ClassRunner.class)
public class SalesForceDaoImplTest {

@InjectMocks
private SalesForceDaoImpl salesForceDao;
@Mock
private ForceApi forceApiMock;
@Mock
private ApiConfig apiConfigMock;
@Mock
private Configuration configMock;
@Mock
JsonObject jsonobject;


@Before
public void setup() {
    initMocks(this);
    when(configMock.getAppConfiguration()).thenReturn(jsonobject);
    when(jsonobject.getString(anyString())).thenReturn("test");
    when(salesForceDao.getForceAPI()).thenReturn(forceApiMock);
    when(new ApiConfig()).thenReturn(apiConfigMock);
    when(new ForceApi(apiConfigMock)).thenReturn(forceApiMock);
}

我试图以这种方式做,但它不起作用。 我的DAO类正在扩展抽象DAO类

public void checkPrinterStatus(){

    try {
        logger.info("Check -------------- ");

        Thread.sleep(2000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    PrintService printer = configParamPrintService.getPrintService();
    logger.info("State " + printer.isAttributeCategorySupported(PrinterState.class));
    Set<Attribute> attributes = getAttributes(printer);
    for(Attribute attr : attributes){
        logger.info(attr.getName());
    }



}

public static Set<Attribute> getAttributes(PrintService printer) {
    Set<Attribute> set = new LinkedHashSet<Attribute>();

    //get the supported docflavors, categories and attributes
    Class<? extends Attribute>[] categories = (Class<? extends Attribute>[]) printer.getSupportedAttributeCategories();
    DocFlavor[] flavors = printer.getSupportedDocFlavors();
    AttributeSet attributes = printer.getAttributes();

    //get all the avaliable attributes
    for (Class<? extends Attribute> category : categories) {
        for (DocFlavor flavor : flavors) {
            //get the value
            Object value = printer.getSupportedAttributeValues(category, flavor, attributes);

            //check if it's something
            if (value != null) {
                //if it's a SINGLE attribute...
                if (value instanceof Attribute)
                    set.add((Attribute) value); //...then add it

                //if it's a SET of attributes...
                else if (value instanceof Attribute[])
                    set.addAll(Arrays.asList((Attribute[]) value)); //...then add its childs
            }
        }
    }

    return set;
}

1 个答案:

答案 0 :(得分:0)

可能这是一个迟到的回复,但我相信它对我们这些程序员来说仍然有用。

免责声明:我从未与PowerMockito合作,但我已经使用过PowerMock 至于troig的建议: PowerMock驱动的单元测试假定您将使用专用的跑步者运行:

@RunWith(PowerMockRunner.class)

在这种情况下,这与问题中陈述的@RunWith(BlockJUnit4ClassRunner.class)冲突,因此RunWith的“插槽”已被占用。

这个特殊的版本仍然可以通过运行最新版本的power mock作为JUnit规则来解决(我假设你运行JUnit)你可以找到一个这样做的例子here 但最重要的是,这是power mock的已知问题之一。

还有其他问题基本上让我得出结论,应该避免使用power mock,不应该在新项目中使用(以及Power Mockito):

  • 使用power mock的单元测试速度很慢(比使用EasyMock要慢得多,如果可以使用它重写)

  • Power Mock有时会使用与jacoco代码覆盖等工具不兼容的字节代码,因此声纳不包括使用power mock测试的单元类别,或者至少做错了

  • 负责在maven中运行测试的Surefire插件具有并行运行多个单元测试的功能。有时用电源嘲笑它是不可能的。

  • 甚至IntelliJ有时也无法运行包含电源模拟测试的套装。

但最重要的是,当你必须使用像power mock这样的工具时,代码可能(并且应该)被重构为更干净和易于理解。关于你的具体问题:

你的班级违反了编码原则,即该班级不应该关注自己的依赖性。这里DAO实际上“构造”并配置另一个(外部)服务供以后使用。

我建议你观看Misko Hevery about clean code的精彩演讲,以便更好地理解我的意思

再次,在你的例子中。将ForceApi维护为依赖注入框架构建的依赖项要好得多(我发现你已经使用@Inject,所以你走的是正确的轨道)

看看这个实现:

public abstract class AbstractDao {

  @Inject // this one is constructed and injected by your favorite DI framework in real use cases
  private ForceApi forceApi;

  public void doSomething() {
       // do your dao stuff here
       forceApi.callSomeAPIMethod();
       // do your dao stuff here
  }    
}

现在进行单元测试你不再需要电源模拟了。它足以根据情况使用简单的Mock甚至Stub。您所需要的只是提供一个构造函数,该构造函数将采用类型为ForceApi的参数或者可能是一个setter(您可以考虑将其设置为私有,以便没有人能够在测试之外调用它)。

我没有提供足够的信息,但我提供的设计可能无需为DAO设置一个Abstract类,这在某些情况下也会有所帮助,因为继承有时可能是维持相当重的“义务”(至少考虑一下)。也许在这种情况下,继承只是为了支持这种getForceAPI行为。在这种情况下,随着项目的增长,可能会在这个AbstractDAO中添加一些方法,因为它很方便,但这些方法将“透明地”添加到所有DAO的整个层次结构中。这种结构变得脆弱,因为如果至少有一种方法改变了它的实现,DAO的整个层次结构可能会失败。

希望这有帮助