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



我有一个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类正在扩展抽象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的"插槽"已被占用。

这个特殊的问题仍然可以通过运行最新版本的powermock作为JUnit的规则来解决(我假设您运行的是JUnit)但归根结底,这是权力模拟的一个已知问题。

还有其他问题,这基本上让我得出结论,应该避免在新项目中使用功率模拟(以及功率模拟):

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

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

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

  • 甚至IntelliJ有时也无法运行包含功率模拟测试的程序集。

但最重要的是,当你必须使用powermock这样的工具时,可能可以(也应该)重构代码,使其更干净、更容易理解。关于您的特定问题:

你的类违反了编码原则,即类不应该照顾自己的依赖关系。在这里,DAO实际上"构造"并配置了另一个(外部)服务,以备日后使用。

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

再说一遍,在你的例子中。将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
  }    
}

现在,对于单元测试,您不再真正需要power mock了。根据情况,使用一个简单的Mock甚至Stub就足够了。您所需要的只是提供一个构造函数,该构造函数将接受类型为ForceApi的参数,或者可能是一个setter(您可以考虑将其设置为私有包,这样就没有人能够在测试之外调用它)。

我没有足够的信息来回答你的问题,但我提供的设计可能可以消除为DAO提供抽象类的需要,这在某些情况下也很有帮助,因为继承有时可能是一项相当繁重的维护"义务"(至少要考虑一下)。在这种情况下,继承可能只是为了支持这种getForceAPI行为。在这种情况下,随着项目的发展,可能会有一些方法被添加到这个AbstractDAO中,只是因为这样做很方便,但这些方法此时会"透明"地添加到所有DAO的整个层次结构中。这种构造变得脆弱,因为如果至少有一个方法更改其实现,那么整个DAO层次结构可能会失败。

希望这能帮助

相关内容

  • 没有找到相关文章

最新更新