繁体   English   中英

在抽象类中模拟新对象实例

[英]Mock a New Object instance in a Abstract Class

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

public abstract class AbstractDao {

@Inject
private Configuration configuration;

public ForceApi getForceAPI() {
    ApiConfig config = new ApiConfig();
    config.setClientId("test");
    config.setClientSecret("test");
    config.setUsername("test");
    config.setPassword("test");
    config.setLoginEndpoint("test");
    return new ForceApi(config);
}

}

我正在尝试以这种方式进行操作,但无法正常工作。 我的DAO课正在扩展Abstract DAO课

@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);
}

可能这是一个较晚的答复,但我相信它对我们中某些程序员仍然有用。

免责声明:我从未使用过PowerMockito,但是我已经使用过很多PowerMock。关于troig的建议:PowerMock驱动的单元测试假设您将使用专用的运行器运行:

@RunWith(PowerMockRunner.class)

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

通过将最新版本的Power Mock作为JUnit的规则运行(我假设您正在运行JUnit),仍然可以解决这一特定问题。您可以在此处找到执行此操作的示例,但最重要的是,这是Power Mock的已知问题之一。

从根本上来说,还有其他一些问题使我得出结论,应该避免使用Power Mock,并且不应该在新项目中使用它(以及Power Mockito):

  • 带有电源模拟的单元测试速度较慢(如果可以使用它重写,则比EasyMock慢得多)

  • Power Mock有时会检测与Jacoco代码覆盖率之类的工具不兼容的字节码,因此声纳无法涵盖使用Power Mock测试的类单元,或者至少是错误的

  • 负责在Maven中运行测试的Surefire插件具有并行运行多个单元测试的功能。 有时用权力嘲弄是不可能的。

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

但是最重​​要的是,当您不得不使用诸如Power Mock之类的工具时,可能(并且应该)将代码重构为更加清晰和易于理解。 关于您的特定问题:

您的类违反了编码原则,该原则说该类不应照顾自己的依赖性。 在这里,DAO实际上是“构造”并配置另一个(外部)服务以供以后使用。

我建议您观看Misko Hevery 关于干净代码的精彩演讲,以更好地理解我的意思。

同样,在您的示例中。 最好将ForceApi保持ForceApi依赖关系注入框架构造的依赖关系(我看到您已经在使用@Inject所以您ForceApi正确的轨道上)

看一下这个实现:

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的整个层次结构可能会失败。

希望这可以帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM