Java 测试私有静态方法

Java 测试私有静态方法,java,unit-testing,mocking,static-methods,jmockit,Java,Unit Testing,Mocking,Static Methods,Jmockit,您好,我想测试generateKey方法和Dispatcher发送的消息。我试图模拟类和公共方法verifyOtherDetails()。在它里面,我创建了一个期望,即dispatcher方法有一个文本值,但它总是传递。任何帮助都将不胜感激 请参阅底部,了解我尝试的代码,谢谢 abstract class KeyGen { private static void generateKey(String key, String username){ if(Strings.isNullO

您好,我想测试generateKey方法和Dispatcher发送的消息。我试图模拟类和公共方法verifyOtherDetails()。在它里面,我创建了一个期望,即dispatcher方法有一个文本值,但它总是传递。任何帮助都将不胜感激

请参阅底部,了解我尝试的代码,谢谢

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)));
          }
        };
      }
    };
  }
}
抽象类KeyGen{
私有静态void generateKey(字符串键、字符串用户名){
if(Strings.isNullOrEmpty(key)){
Dispatcher.dispatch(新的WarningString(String.format(“用户%s的密钥为null或空”,用户名));
}否则{
Dispatcher.dispatch(新的InfoString(String.format(“该键对于用户%s是正确的”,用户名));
}
}
public void verifyOtherDetails(字符串地址、地图收藏夹){
字符串键=”;
字符串username=“”;
generateKey(键、用户名);
}
}
公共类TestKeyGen{
@试验
public void testKey(){
新模型(){
@Mock()
公共无效验证其他详细信息(){
String key=“sfjhlkjfkjdhlsk”;
最终字符串username=“Daniel”;
新期望(){
{
Dispatcher.dispatch(新的WarningString(String.format(“用户%s的密钥为null或空”,用户名));
}
};
}
};
}
}

考虑到您的设计,我认为很难测试您的方法。基本上这是因为您使用的是dispatcher类的静态方法,所以无法轻松地对其进行模拟

不过你有很多选择。您可以在测试中订阅dispatchers消息,并检查预期消息是否到达。这是侵入性最小的测试,可作为集成测试

另一个选项是将dispatcher静态调用包装在接口中,并将此接口的模拟注入
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);
  }
}

考虑到你的设计,我认为很难测试你的方法。基本上这是因为您使用的是dispatcher类的静态方法,所以无法轻松地对其进行模拟

不过你有很多选择。您可以在测试中订阅dispatchers消息,并检查预期消息是否到达。这是侵入性最小的测试,可作为集成测试

另一个选项是将dispatcher静态调用包装在接口中,并将此接口的模拟注入
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);
  }
}

问题中测试的固定版本:

@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
方法。)

问题中测试的固定版本:

@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
方法。)

已经有很多资料在测试私有方法,包括google的热门方法。这些回答了你的问题吗?我见过反射的用法,但我想看看是否有更干净的方法来验证这个方法。我是JMockit的新手,对模拟对象没有太多经验。已经有很多关于测试私有方法的资料了——包括,如果你在谷歌上搜索热门的内容。这些回答了你的问题吗?我见过反射的用法,但我想看看是否有更干净的方法来验证这个方法。我是JMockit新手,对模拟对象没有太多经验。你能给我举个例子吗。我理解你的意思,但就我目前所知,在尝试之前还需要更多的阅读。第一部分(订阅dispatcher消息)我无能为力,因为我不知道你如何订阅应用程序/框架中的Receive消息。我想你会的:)。但我将提供一个包装器示例,请稍等。第三个选项的优点是,如果JMockit允许模拟公共静态方法,那么您可以通过模拟调用
KeyGen.generateKey
来测试
VerifyingKeyGen
,您可以为我指出一个示例的方向吗。我理解你的意思,但就我目前所知,在尝试之前还需要更多的阅读。第一部分(订阅dispatcher消息)我无能为力,因为我不知道你如何订阅应用程序/框架中的Receive消息。我想你会的:)。但我将提供一个包装器示例,请稍候。第三个选项的优点是,如果JMockit允许模拟公共静态方法,那么您可以通过模拟调用
KeyGen.generateKey
来测试
VerifyingKeyGen