Daniel Devlin
Daniel Devlin

Reputation: 115

Testing a private Static method

Hi I want to test the generateKey method and the messages being dispatched by the Dispatcher. I have tried to mock the class and the public method verifyOtherDetails(). Inside it I created an expectation that the dispatcher method had a literal value but it always passes. Any help would be appreciated.

See bottom for my attempted code thanks.

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

Upvotes: 2

Views: 1746

Answers (2)

Rog&#233;rio
Rog&#233;rio

Reputation: 16380

Fixed version of the test in the question:

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

(Provided WarningString implements the equals method.)

Upvotes: 2

Sam Holder
Sam Holder

Reputation: 32936

Given your design I'd say its difficult to test your method. Basically this is because you are using static methods of the dispatcher class so you can't easily mock it.

you have a coupe of options though. you could subscribe to the dispatchers messages in your tests and check that the expected messages arrive. This is the least invasive, and serves as an integration test.

The other option is to wrap your dispatcher static calls in an interface and inject a mock of this interface into your KeyGen class then test through your public method that the methods on the interface are called.

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

A third option is to move the private method to a different static class and make it public, then you can test that class (with the same issues with your static dispatcher). Then you KeyGen class can become a VerifyingKeyGen which just verifies then delegates to the other method for actually generating the key. this nicely separates the 2 concerns that you have, ie generating the new key and verifying the deatils

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

Upvotes: 2

Related Questions