Java 静态实例上的模拟方法

Java 静态实例上的模拟方法,java,unit-testing,mockito,Java,Unit Testing,Mockito,我的课程是: public class Factory { private static final Factory instance = new Factory(); private Factory() { } public static Factory getInstance() { return instance; } private Client client = null; //To be mocked //Failing

我的课程是:

public class Factory {
   private static final Factory instance = new Factory();
   private Factory() {
   }
   public static Factory getInstance() {
       return instance;
   }
   private Client client = null;

   //To be mocked
   //Failing at this point 
   //Not actually using mocked method
   public Client getClient(Properties properties) {
      //doSomething
      //...
      return client;
   }
}
在另一类中,上述方法用作:

public class Service {
  protected Client client = null;
  protected void keySetup() {
     //Should be mocked
     client = Factory.getInstance().getClient(properties());

     ...
     ...
  }
}
对于keySetup()方法的单元测试,我试图模拟工厂.getInstance().getClient(properties()),但失败了

我试着做以下几点:

@Test
public void testKeySetupTrue(){
    Client client = mock(Client.class); 
    Factory factory = mock(Factory.class);
    ReflectionTestUtils.setField(factory, "client", client);    
    Properties properties = mock(Properties.class);

    Mockito.doReturn(client).when(factory)
    .getClient(properties);

    Service service = new Service();

    service.keySetup();
    ...
    ...
}
当我在调试模式下运行时,我看到它实际上正在执行模拟的getClient(Properties)


如何解决这个问题

静态最终版
不是一个好的设计。 最好是注入依赖项,让框架(spring或其他)担心控制单例。 也就是说, 就你而言,
使用反射设置带有模拟工厂的
Factory实例
变量。

这不适用于Mockit,因为此框架不能(实际上也不应该)模拟静态和最终方法和/或类根据@MaciejKowalski的答案,使用powermockito代替,但我不建议您这样做,因为此框架修改字节码,因此您没有原始设计的代码,这可能会导致一些不想要的/意外的行为。我建议重新设计您的类,以便能够测试代码。同意。单身汉在大多数情况下比他们值得花的时间更麻烦,尤其是在测试方面。在这种情况下,所有的问题都是自制的,应该通过重构来解决,而不是使用新的工具(如PowerMock或类似工具),特别是因为PowerMock只解决了原本不应该解决的问题。