为了账号安全,请及时绑定邮箱和手机立即绑定

如何在接口默认方法中对新对象创建进行单元测试?

如何在接口默认方法中对新对象创建进行单元测试?

MYYA 2023-04-26 16:29:44
接口中有一个创建新对象并使用其功能的默认方法。所以我需要嘲笑它。但是如果不创建另一个返回新实例的默认方法,我就无法弄清楚。到目前为止,我曾经创建过处理对象创建的工厂,而不是模拟工厂方法。但不能在接口中执行此操作,因为接口不能具有在这种情况下作为工厂的实例变量。还有其他想法吗?我想在项目中保持一致,但现在我有两种不同的方法来避免在方法中创建对象。这是一个例子:public interface ISomeInterface{    default Integer callMe( )    {        Object someObject = new Object( ); // need to mock this        Integer result = someObject.finish();        result = result + 1;        return result;    }}当我不使用这样的接口时,我曾经用工厂重构代码;default Integer callMeNotInterfaceClass( ){    Object someObject = new Object( );    Integer result = instanceFactory.create().finish(); // I can mock create() method     result = result + 1;    return result;}我为包装器方法实现的唯一解决方案:public Integer callMe( ){    Object someObject = new Object( );    Integer result = wrapperMethodCall.finish(); // only solution so far. But now I have 2 different approaches in the project to avoid object creation.    result = result + 1;    return result;}default Object wrapperMethodCall() {    return new SomeObject().someMethodsToBeMocked();}
查看完整描述

1 回答

?
守着星空守着你

TA贡献1799条经验 获得超8个赞

像往常一样,单元测试迫使您考虑类的设计。

首先,您应该注意到您有两种主要的不同类型的对象。

有些对象是值:它们是不可变的,可以存在于多个副本中,是可比较的(并且hashCode也有一个)。这是一种易于存储在数据库中的对象。如果您对 Kotlin 有所了解,您就会听说过data classes: 就是这样。

其他一些具有实体语义的对象:它们是可变的,比较它们没有意义,而且通常只有它们的一个副本。它们是做某事的对象。

具有实体语义的对象是您需要在单元测试中模拟的对象,而您不需要模拟值。为了传递模拟,这些对象必须作为构造函数的参数注入到类中。

在您的代码片段中,您在函数中创建了一个对象,该对象似乎具有实体的语义(值什么都没有finish),这就是您遇到问题的原因:您无法进行单元测试,因为您无法模拟该实体.

解决方案很简单:要么在方法中注入对象:

public interface ISomeInterface

{

    default Integer callMe(Object someObject)

    {

        Integer result = someObject.finish();

        result = result + 1;


        return result;

    }


    ...

}

或者你在类中注入对象:


public interface ISomeInterface

{

    default Integer callMe()

    {

        Integer result = finishObject();

        result = result + 1;


        return result;

    }


    // classes will need an instance of the object to implement this

    Integer finishObject(); 


    ...

}

在这两种情况下,实现您的接口的类要么负责在调用方法时提供对象本身,要么负责返回方法的值finish。


但请记住:如果您在这些类的方法中创建对象,对它们进行单元测试也会变得困难。使用工厂模式在静态方法中创建实体对象并将这些对象传递给构造函数。


如果遵循这条经验法则,类和方法的单元测试将变得更容易:当对象具有语义值时,在更高级别创建它(如果可能)并将其作为构造函数或方法的参数main传递。


查看完整回答
反对 回复 2023-04-26
  • 1 回答
  • 0 关注
  • 114 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信