【问题标题】:Testing a private Static method测试私有静态方法
【发布时间】:2014-10-31 15:45:37
【问题描述】:

您好,我想测试 generateKey 方法和 Dispatcher 发送的消息。我试图模拟类和公共方法 verifyOtherDetails()。在其中,我创建了一个期望,即调度程序方法具有文字值,但它总是通过。任何帮助将不胜感激。

请参阅底部的我尝试的代码谢谢。

abstract class KeyGen {

  private static void generateKey(String key, String username){
    if(Strings.isNullOrEmpty(key)){
      Dispatcher.dispatch(new WarningString(String.format("The key is null or empty for user %s", username)));
    }else{
      Dispatcher.dispatch(new InfoString(String.format("The key is correct for user %s", username)));
    }
  }

  public void verifyOtherDetails(String address, Map<String, String> favouriteFilms){
    String key ="";
    String username ="";
    generateKey(key, username);
  }
}

public class TestKeyGen {

  @Test
  public void testKey() {
    new MockUp<KeyGen>() {
      @Mock()
      public void verifyOtherDetails() {

        String key = "sfjhlkjhfkjdhlsk";
        final String username = "Daniel";
        new Expectations() {
          {
            Dispatcher.dispatch(new WarningString(String.format("The key is null or empty for user %s", username)));
          }
        };
      }
    };
  }
}

【问题讨论】:

  • 已经有很多关于测试私有方法的材料——包括other answers on SO,如果你在谷歌上搜索到the text of this question's subject line,就包括最热门的。这些能回答你的问题吗?
  • 我见过反射的使用,但我想看看是否有更清洁的方法来验证该方法。我是 JMockit 的新手,对模拟对象没有太多经验。

标签: java unit-testing mocking static-methods jmockit


【解决方案1】:

鉴于您的设计,我会说很难测试您的方法。基本上这是因为您使用的是调度程序类的静态方法,因此您不能轻易地模拟它。

不过,您有多种选择。您可以在测试中订阅调度程序消息并检查预期消息是否到达。这是侵入性最小的,可用作集成测试。

另一种选择是将您的调度程序静态调用包装在一个接口中,并将该接口的模拟注入您的KeyGen 类,然后通过您的公共方法测试接口上的方法是否被调用。

public interface DispatchWrapper{
    void dispatch(IString stringToDispatch);
}

public class StaticDispatcher : DispatchWrapper{
    void dispatch(IString stringToDispatch)
    {
            Dispatcher.dispatch(stringToDispatch);
    }
}

abstract class KeyGen {
  private DispatchWrapper wrapper;

  public KeyGen(DispatchWrapper wrapper){
      this.wrapper = wrapper;
  }
  private static void generateKey(String key, String username){
    if(Strings.isNullOrEmpty(key)){
      wrapper.dispatch(new WarningString(String.format("The key is null or empty for user %s", username)));
    }else{
      wrapper.dispatch(new InfoString(String.format("The key is correct for user %s", username)));
    }
  }

  public void verifyOtherDetails(String address, Map<String, String> favouriteFilms){
    String key ="";
    String username ="";
    generateKey(key, username);
  }
}

第三种选择是将私有方法移动到不同的静态类并使其公开,然后您可以测试该类(与您的静态调度程序有相同的问题)。然后你的 KeyGen 类可以变成一个VerifyingKeyGen,它只是验证然后委托给另一个方法来实际生成密钥。这很好地分开了您所关心的 2 个问题,即生成新密钥和验证细节

public static class KeyGen {

  public static void generateKey(String key, String username){
    if(Strings.isNullOrEmpty(key)){
      Dispatcher.dispatch(new WarningString(String.format("The key is null or empty for user %s", username)));
    }else{
      Dispatcher.dispatch(new InfoString(String.format("The key is correct for user %s", username)));
    }
  }

abstract class VerifyingKeyGen{

  public void verifyOtherDetails(String address, Map<String, String> favouriteFilms){
    String key ="";
    String username ="";
    KeyGen.generateKey(key, username);
  }
}

【讨论】:

  • 你能给我指出一个例子的方向吗?我理解你的意思,但据我所知,在尝试之前还需要阅读更多内容。
  • 我对第一个问题(订阅调度程序消息)无能为力,因为我不知道您如何订阅应用程序/框架中的接收消息。我假设你这样做:)。但我会提供一个包装示例,请稍等。
  • 第三个选项的一个优点是,如果 JMockit 允许模拟公共静态方法,那么您可以通过模拟对 KeyGen.generateKey 的调用来测试 VerifyingKeyGen
【解决方案2】:

问题中测试的固定版本:

@Tested KeyGen keyGen;
@Mocked Dispatcher dispatcher;

@Test
public void testKey() {
    keyGen.verifyOtherDetails("???", null);

    final WarningString warning = 
        new WarningString("The key is null or empty for user ");

    new Verifications() {{ Dispatcher.dispatch(warning); }};
}

(提供WarningString实现equals方法。)

【讨论】:

    猜你喜欢
    • 2015-04-17
    • 1970-01-01
    • 2016-06-28
    • 2017-06-19
    • 2012-07-14
    • 2023-04-01
    • 2015-06-05
    • 2010-11-04
    • 2018-12-03
    相关资源
    最近更新 更多