我有一个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层次结构可能会失败。
希望这能帮助