我有一个 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 的“槽位”已被占用。
这个特定的问题仍然可以通过运行最新版本的电源模拟作为 JUnit 的规则来解决(我假设您运行 JUnit)您可以找到一个执行此操作的示例 here 但最重要的是,这是电源模拟的已知问题之一。
还有其他问题基本上让我得出结论,应该避免使用 Power Mock,并且不应在新项目(以及 Power Mockito)中使用它:
使用 power mock 的单元测试很慢(比使用 EasyMock 慢得多,如果可以重写使用它的话)
Power Mock 有时会检测与 jacoco 代码覆盖率等工具不兼容的字节代码,因此声纳不会覆盖使用 Power Mock 进行单元测试的类,或者至少会出错
负责在maven中运行测试的Surefire插件具有并行运行多个单元测试的功能。有时使用权力模拟是不可能的。
即使 IntelliJ 有时也无法运行包含强大模拟测试的套件。
但最重要的是,当您必须使用像 power mock 这样的工具时,代码可能可以(并且应该)重构为更加干净和易于理解。关于您的具体问题:
您的类违反了类不应该处理自身依赖关系的编码原则。这里 DAO 实际上“构建”并配置了另一个(外部)服务以供以后使用。
建议您观看 Misko Hevery 的精彩讲座 about clean code为了更好地理解我的意思
再说一次,在你的例子中。最好将 ForceApi
维护为依赖注入(inject)框架构建的依赖项(我看到您已经使用 @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
}
}
现在,对于单元测试,您不再需要电源模拟了。根据情况使用简单的 Mock 甚至 Stub 就足够了。您所需要的只是提供一个构造函数,该构造函数将采用 ForceApi
类型的参数,或者可能是一个 setter(您可以考虑将其封装为私有(private),以便没有人能够在测试之外调用它)。
我没有从你的问题中得到足够的信息,但我提供的设计可能可以消除对 DAO 抽象类的需要,这在某些情况下也很有帮助,因为继承有时可能是维护的一项相当繁重的“义务”(至少考虑一下这一点)。也许在这种情况下,继承只是为了支持此 getForceAPI
行为。在这种情况下,随着项目的发展,可能会因为这样做方便而将一些方法添加到该 AbstractDAO 中,但这些方法此时将“透明”地添加到所有 DAO 的整个层次结构中。这种构造变得脆弱,因为如果至少一种方法更改其实现,则整个 DAO 层次结构可能会失败。
希望这有帮助
关于java - 模拟抽象类中的新对象实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34399767/