0

I have a following code

public class Component extend Framework {
  private Integer someInt;  
  private String someString;    
  public Integer getSomeInt() {
    return someInt;
  }    
  public String getSomeString() {
    return someString;
  }
  public void activate() {
     Integer tempInt = (Integer)getProperties("key"); // From Framework
     if (tempInt == null) {
         tempInt = (Integer)getRequest().getProperties("key"); // From Framework        
     }

     if(tempInt == null)
        tempInt = (Integer)getBind().getProperties("key"); // From Frameowrk 
     someString = makeServiceCall("http://.....?key=tempInt");
  }
}

Basically activate() method is called by the framework in order to access internal state of the framework to construct Component object. activate() is sort of like a setter for the Component object. If I were to unit test the code above, what would be the best way to do it without having to have framework running?

One way would be to mock out Component class and stub the super.getProperties... calls, however if we mock the class in question, what is the point of testing to begin with?

user_1357
  • 7,766
  • 13
  • 63
  • 106
  • That depends on the method you like to unit test. If you are unit testing `activate()` method, then it is perfectly fine to stub super.getProperties() method. – Mrinal Jan 03 '16 at 18:08
  • I am unit testing the activate(). Is there a better way to stub out hidden internal properties of framework without having to mock Component? – user_1357 Jan 03 '16 at 18:12
  • 1
    A good starting point is take care about the different results from `super.getProperties()` call and then test the behaviour that you expect for this results. So, to ensure this, create a stub to include the expected framework's behaviour. – Lompa Jan 03 '16 at 18:15
  • 2
    Why are you calling `super.getProperties()` instead of only `getProperties()` ? In that case, you could override it to pass mock value. – Mrinal Jan 03 '16 at 18:20
  • To make it explicit that the function comes from the inheritance for demo purpose. – user_1357 Jan 03 '16 at 18:23
  • `tempInt` can never be `null`. It is a primitive. – Makoto Jan 03 '16 at 18:46
  • @Makoto Yes, edited. – user_1357 Jan 03 '16 at 19:02
  • 1
    Thanks for that. Now, what's the actual point of `tempInt`? It's not used anywhere else. – Makoto Jan 03 '16 at 19:03
  • @Mayumi: remove the `super.` from your code. The comment is sufficient and calls to `super.xxx` prevent proper testing and proper polymorphics. Yet, the only side effect that could be tested is the call to `makeServiceCall`. Do you want to test that this method is called only if `getProperties("key")` and `getRequest.getProperties("key")` are `null`? I think the solution could be explained easier if you remove at least the first default case (`getRequest.getProperties("key")`). – CoronA Jan 03 '16 at 19:14
  • @CoronA right, changed. Thanks. – user_1357 Jan 03 '16 at 19:35
  • @CoronA Code is setting an instance values based on absence/presence of key in properties. So the behaviour I am attempt to test is state of instance variable with absence/presence of key in one of those internal context. – user_1357 Jan 03 '16 at 19:43
  • I assume that the last line of activate is not correctly indented and not part of the if? And I assume that it should be: `someString = makeServiceCall("http://.....?key=" + tempInt);` Can you correct it if my assumptions are correct. – CoronA Jan 03 '16 at 21:38

3 Answers3

1

Use Mockito. Spy the Component class and mock the methods getRequest() and getBind(). Finally, call the activate() method directly from your unit test.

DwB
  • 37,124
  • 11
  • 56
  • 82
1

I will show how to test one edge case

void testServiceCallWithNoKeyPropertyFound() {
  Component componentUnderTest = new Component() {
    Integer getProperties(String key) {
       return null; // property should not be found
    }

    Request getRequest() {
      return new Request(...); //this request should not contain a property named "key", 
    }

    Bind getBind() {
      return new Bind(...); //this bind should not contain a property named "key"
    }

    String makeServiceCall(String url) {
      if (url.endsWith("null")) {
        return success;
      }
      throw new AssertionError("expected url ending with null, but was " + url);
    }

  };
  componentUnderTest.activate();
  assertThat(componentUnderTest.getSomeString(), equalTo("success"));
}

Using Mockito (spys) can make this example much more concise. But this would hide the principles how to design the test.

There are some more edge cases:

void testServiceCallWithPropertyFoundInComponent() ...
void testServiceCallWithPropertyFoundInRequest() ...
void testServiceCallWithPropertyFoundInBind() ...
CoronA
  • 7,717
  • 2
  • 26
  • 53
-1

I think it could be a smell of bad design. Maybe you should consider composition instead of inheritance? It would be more testing friendly and more objective. Why Component is inheriting from Framework class?

public class Component {
  private int someInt;  
  private String someString;  
  private Framework framework;  

  public Component(Framework framework) {
    this.framework = framework
  }

  public int getSomeInt() {
    return someInt;
  }    
  public String getSomeString() {
    return someString;
  }
  public void activate() {
     int tempInt = framework.getProperties("key"); // From Framework
     if (tempInt == null) {
         tempInt = framework.getRequest().getProperties("key"); // From Framework        
     }

     if(tempInt == null)
        tempInt = framework.getBind().getProperties("key"); // From Frameowrk 
        someString = makeServiceCall("http://.....?key=tempInt");
  }
}
  • That would be great than I can inject appropriate instance instead, but framework requires inheritance. – user_1357 Jan 03 '16 at 18:45