[英]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.