Java 用静态方法处理Final类

Java 用静态方法处理Final类,java,junit,mocking,refactoring,mockito,Java,Junit,Mocking,Refactoring,Mockito,我有一个方法,我想测试。在这里,我调用了最后一个Hybris类的静态方法(Config.getParameter(“aString”))。我想嘲弄它,但我发现,你不能用Mockito这样做。那么,什么才是解决这个问题的好方法呢?问题是,我正在考虑重构。但是我不能更改Config类,因为它来自Hybris 如何更改要测试的类,以便影响Config.getParameter(“aString”)调用 谢谢 一种解决方案是创建一个接口,其方法(或多个方法)与您期望的Config类相匹配。然后您可以执行

我有一个方法,我想测试。在这里,我调用了最后一个Hybris类的静态方法(
Config.getParameter(“aString”)
)。我想嘲弄它,但我发现,你不能用Mockito这样做。那么,什么才是解决这个问题的好方法呢?问题是,我正在考虑重构。但是我不能更改Config类,因为它来自Hybris

如何更改要测试的类,以便影响
Config.getParameter(“aString”)
调用


谢谢

一种解决方案是创建一个接口,其方法(或多个方法)与您期望的
Config
类相匹配。然后您可以执行以下操作:

  • 创建一个在生产中使用
    Config
    的实现
  • 为您的测试创建一个模拟
使用Java 8的简化示例:

// The interface
public interface MyInterface
{
    String getParameter(String paramName);
}

// Class using the interface
public final class MyClass
{
    private final MyInterface intf;

    // For testing...
    public MyClass(final MyInterface intf)
    {
        this.intf = Objects.requireNonNull(intf);
    }

    // In production...
    public MyClass()
    {
        this(Config::getParameter);
    }

    // etc
}

// Test class
@Test
public void whatever()
{
    final MyInterface intf = mock(MyInterface.class);
    // set up the mock, then...

    final MyClass myClass = new MyClass(intf);
    // test myClass
}

一种解决方案是创建一个接口,其方法(或多个方法)与您期望的
Config
类相匹配。然后您可以执行以下操作:

  • 创建一个在生产中使用
    Config
    的实现
  • 为您的测试创建一个模拟
使用Java 8的简化示例:

// The interface
public interface MyInterface
{
    String getParameter(String paramName);
}

// Class using the interface
public final class MyClass
{
    private final MyInterface intf;

    // For testing...
    public MyClass(final MyInterface intf)
    {
        this.intf = Objects.requireNonNull(intf);
    }

    // In production...
    public MyClass()
    {
        this(Config::getParameter);
    }

    // etc
}

// Test class
@Test
public void whatever()
{
    final MyInterface intf = mock(MyInterface.class);
    // set up the mock, then...

    final MyClass myClass = new MyClass(intf);
    // test myClass
}

除了Mockito之外,您还可以使用一个工具调用,它在您的用例中会很有帮助

除了Mockito之外,您还可以使用一个工具调用,它在您的用例中会很有帮助

有两种方法:

1.重构代码并引入ConfigWrapper(例如)接口:

public interface ConfigWrapper {
   public String getParameter(String parameter);

public class ConfigWrapperImpl implements ConfigWrapper{
   public String getParameter(String parameter){
      return Config.getParameter(parameter);
   }
}
然后,您应该重构代码并通过注入ConfigWrapper替换Config.*用法。当您编写测试时,您可以使用mockito轻松地模拟ConfigWrapper(因为您使用的是非静态方法)

  • 第二种方法是使用PowerMock而不是mockito:

    PowerMock.mockStatic(包含staticmethod.class的类)


  • 有关更多信息,请参见:

    有两种方法:

    1.重构代码并引入ConfigWrapper(例如)接口:

    public interface ConfigWrapper {
       public String getParameter(String parameter);
    
    public class ConfigWrapperImpl implements ConfigWrapper{
       public String getParameter(String parameter){
          return Config.getParameter(parameter);
       }
    }
    
    然后,您应该重构代码并通过注入ConfigWrapper替换Config.*用法。当您编写测试时,您可以使用mockito轻松地模拟ConfigWrapper(因为您使用的是非静态方法)

  • 第二种方法是使用PowerMock而不是mockito:

    PowerMock.mockStatic(包含staticmethod.class的类)


  • 有关更多信息,请参见:

    如果要使用DI容器/框架,更好的方法是依靠它将所需的配置参数注入带注释的
    字符串
    字段。例如,类似于
    @Inject@Named(“aString”)字符串configParam
    。这可以通过CDI、Spring和Guice实现,尽管细节有所不同。优点是它可以简化客户端代码。如果要使用DI容器/框架,更好的方法是依靠它将所需的配置参数注入带注释的
    字符串
    字段。例如,类似于
    @Inject@Named(“aString”)字符串configParam
    。这可以通过CDI、Spring和Guice实现,尽管细节有所不同。优点是它可以简化客户端代码。