testing method signatures and mockbox

Hi all,
Starting to get into MockBox and really liking it so far. We use it
standalone with mxUnit as our unit test framework. I will freely
admit that a) I am a relative newbie in this area and b) this question
is really more to do with mocking/unit testing in general vs any
mocking framework. But MockBox is what we are using so you guys get
to read my ramblings :slight_smile:

My question is how to test the contract between a function and its
dependencies (be it internal or external) when you have mocked away
the dependency. I have created a rather contrived example below.

Say we have a component "a" that can take a string and either reverse
or not based on random chance. It relies on component "b" to take
care of the random chance part. It could like something like this.

component name="a" {
  property any b;

  //DI framework will handle this
  public void function setB(any b){
    variables.b = arguments.b;
  }

  public string function getRandomReverse(required string input){
    if(variables.b.getRandomBool())
      return reverse(arguments.input);
    else
      return arguments.input;
  }

}

component name="b" {
  public boolean function getRandomBool(){
    return (rand() < .5);
  }
}

So far so good. And now we want to unit test "a" and mock away the
dependency on "b"

component extends="mxunit.framework.TestCase"{
  public void function testA(){
    a= new a();

    mockBox = new mockbox.system.testing.MockBox();
    mockBox.prepareMock(a);
    b = mockbox.createStub();
    a.$property(propertyName="b",mock=b);

    b.$("getRandomBool",false);
    assertEquals(a.getRandomReverse("Lance"),"Lance");
    b.$("getRandomBool",true);
    assertEquals(a.getRandomReverse("Lance"),"ecnaL");
  }
}

Still looks good. We are testing the functionality of
a.getRandomReverse in isolation and leaving something else to test
b.getRandomBool

But lets say down the road we modify b.getRandomBool to require a
weighting. So, for example, you pass it .75 it will return true 75%
of the time. component "b" now looks like this.

component name="b" {
  public boolean function getRandomBool(required numeric weight){
    return (rand() < arguments.weight);
  }
}

If we fail to update the calling code in component "a" the function
getRandomReverse would be good and broken. But our unit test will
miss the breaking change because we have mocked away the dependency
and thus are never testing the contract.

So my question is...how do we handle this? How can I test the
software in isolation and still ensure our code is playing nicely with
it's dependencies? I feel like there is a whole other class of
testing that I am missing here.

Thanks in advance. And p.s. a link to a good web resource on this
scenario and a short note that says "read this and learn something" is
a perfectly acceptable answer :slight_smile:

Lance

This is a clear example of why there is an open/closed principle,
classes should be open for extension, but closed for modification. If
you change the signature of a public method, you are breaking the
contract that class has with all the other code that uses it. You
would have had to change the unit test for b to get it to keep
passing, so too would you have to change anything that depends on b,
both tests and code.

But to answer your question, an integration test would (might) have
caught this. They are like unit tests but without the mocks and using
real (although controlled) data. You can use mxunit to write
integration tests as well as unit tests.

Or also there are functional tests, which are like integration tests
but driven by actual UI (through automation hopefully). Selenium and
the like are used for this.

Unit tests don't and can't possibly catch all bugs, they are just a
foundation. Think about unit testing an ORM entity, you can test the
logic in it, and the test might pass but if the table doesn't exist or
has missing columns it would fail miserable in production.

HTH