简体   繁体   English

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

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

I have a AbstractDao class, where I am instantiating Rest Fore API. 我有一个AbstractDao类,在其中实例化Rest Fore API。 I am not able to mock the new forceAPI(config) in Power Mock. 我无法在Power Mock中模拟新的forceAPI(config)。 Please suggest. 请提出建议。

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

}

I am trying to do in this way but it's not working. 我正在尝试以这种方式进行操作,但无法正常工作。 My DAO class is extending Abstract DAO class 我的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);
}

Probably this is a late reply, but I believe it still can be useful to some of us, programmers. 可能这是一个较晚的答复,但我相信它对我们中某些程序员仍然有用。

Disclaimer: I've never worked with PowerMockito but I've used PowerMock quite a lot As for troig's suggestion: PowerMock driven unit test assumes that you'll run with a dedicated runner: 免责声明:我从未使用过PowerMockito,但是我已经使用过很多PowerMock。关于troig的建议:PowerMock驱动的单元测试假设您将使用专用的运行器运行:

@RunWith(PowerMockRunner.class)

In this case this clashes with @RunWith(BlockJUnit4ClassRunner.class) stated in the question, so the "slot" for RunWith is already occupied. 在这种情况下,这与问题中所述的@RunWith(BlockJUnit4ClassRunner.class)冲突,因此RunWith的“插槽”已被占用。

This particular one can still be resolved by running recent versions of power mock as a JUnit's rule (I assume you run JUnit) You can find an example of doing this here But bottom line this is one of known issues with power mock. 通过将最新版本的Power Mock作为JUnit的规则运行(我假设您正在运行JUnit),仍然可以解决这一特定问题。您可以在此处找到执行此操作的示例,但最重要的是,这是Power Mock的已知问题之一。

There are other issues as well which basically made me to come to conclusion that the power mock should be avoided and should not be used in new project (and Power Mockito as well): 从根本上来说,还有其他一些问题使我得出结论,应该避免使用Power Mock,并且不应该在新项目中使用它(以及Power Mockito):

  • The unit test with power mock is slow (much slower than, say with EasyMock if it could be rewritten for using that) 带有电源模拟的单元测试速度较慢(如果可以使用它重写,则比EasyMock慢得多)

  • The Power Mock sometimes instruments the byte code incompatible with tools like jacoco code coverage and as a consequence sonar doesn't cover classes unit tested with power mock or at least does it wrong Power Mock有时会检测与Jacoco代码覆盖率之类的工具不兼容的字节码,因此声纳无法涵盖使用Power Mock测试的类单元,或者至少是错误的

  • Surefire plugin responsible for running tests in maven has a feature of running multiple unit tests in parallel. 负责在Maven中运行测试的Surefire插件具有并行运行多个单元测试的功能。 Sometimes with power mock its not possible. 有时用权力嘲弄是不可能的。

  • Even IntelliJ sometimes fails to run suits that contain power mock tests. 甚至IntelliJ有时也无法运行包含电源模拟测试的诉讼。

But the most important thing is that when you have to use tools like power mock, probably the code can (and should) be refactored to be more clean and easy-to-understand. 但是最重​​要的是,当您不得不使用诸如Power Mock之类的工具时,可能(并且应该)将代码重构为更加清晰和易于理解。 Regarding your particular question: 关于您的特定问题:

Your class violates the coding principle that says that the class should not take care of dependencies of itself. 您的类违反了编码原则,该原则说该类不应照顾自己的依赖性。 Here DAO actually "constructs" and configures another (external) service for a later use. 在这里,DAO实际上是“构造”并配置另一个(外部)服务以供以后使用。

I suggest you to watch an excellent lecture of Misko Hevery about clean code to better understand what I mean 我建议您观看Misko Hevery 关于干净代码的精彩演讲,以更好地理解我的意思。

So again, in your example. 同样,在您的示例中。 Its much better to maintain the ForceApi as a dependency constructed by Dependency Injection framework (I see that you already use @Inject so you're on the right track) 最好将ForceApi保持ForceApi依赖关系注入框架构造的依赖关系(我看到您已经在使用@Inject所以您ForceApi正确的轨道上)

Take a look at this implementation: 看一下这个实现:

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
  }    
}

Now for unit tests you don't really need power mock anymore. 现在,对于单元测试,您实际上不再需要电源模拟。 Its enough to use a simple Mock or even Stub depending on situation. 根据情况,足以使用一个简单的Mock甚至Stub。 All you need is to provide a constructor that will take a parameter of type ForceApi or maybe a setter (you can consider make it package private so that noone would be able to call it outside the test). 您所需要做的就是提供一个构造函数,该构造函数将使用ForceApi类型的参数或一个setter(您可以考虑将其打包为私有,这样任何人都无法在测试之外调用它)。

I don't have enough information out of your question, but the design I've offered probably can eliminate the need to have an Abstract class for the DAO, which is also can be helpful in some cases because inheritance sometimes can be a pretty heavy 'obligation' to maintain (at least think about this). 我没有从您的问题中得到足够的信息,但是我提供的设计可能会消除为DAO创建Abstract类的需要,这在某些情况下也可能会有所帮助,因为继承有时可能会很繁重维持的“义务”(至少要考虑一下)。 And maybe in this case the inheritance is done only to support this getForceAPI behavior. 也许在这种情况下,仅完成继承以支持此getForceAPI行为。 In this case as the project grows, probably some methods will be added into this AbstractDAO just because its convenient to do so, but these methods will 'transparently' be added at this point to the whole hierarchy to all DAOs. 在这种情况下,随着项目的发展,可能会因为其方便性而将某些方法添加到此AbstractDAO中,但是此时这些方法将“透明地”添加到所有DAO的整个层次结构中。 This construction becomes fragile, because if at least one method changes its implementation the whole hierarchy of DAOs can potentially fail. 这种构造变得脆弱,因为如果至少一种方法更改其实现,则DAO的整个层次结构可能会失败。

Hope this helps 希望这可以帮助

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

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