Consider for a moment that m1
was not dependent on m2
.
Now consider that m1
didn't invoke m2
, but rather duplicated the code of m2
within itself.
(In either of the above scenarios, you would test both m1
and m2
, right?)
Now consider what would happen if you refactored m1
to remove duplicate code, by having it invoke m2
. Since this is a true refactoring (i.e., it does not change the behavior of the method), your existing tests should continue to pass.
My point is that the dependence of m1
on m2
is a private implementation detail. You generally want to hide implementation details from your tests, in order to keep them from becoming brittle. Consequently, you should write your tests as if they had no idea about this dependency.
Edit: Adding some code to demonstrate.
Imagine we had written the following code and tests (apologies for any syntax errors; I don't have a compiler handy):
interface Foo {
public void doStuff(int value);
}
interface Bar {
public void doOtherStuff();
}
class MyClass {
private Foo foo;
private Bar bar;
public MyClass(Foo foo, Bar bar) {
this.foo = foo;
this.bar = bar;
}
public void m1() {
foo.doStuff(42);
foo.doOtherStuff();
}
public void m2() {
foo.doStuff(42);
}
}
@Test
public void m1ShouldDoALotOfStuff() throws Exception {
Foo foo = PowerMockito.mock(Foo.class);
Bar bar = PowerMockito.mock(Bar.class);
MyClass sut = new MyClass(foo, bar);
sut.m1();
verify(foo).doStuff(42);
verify(bar).doOtherStuff();
}
@Test
public void m2ShouldJustDoStuff() throws Exception {
Foo foo = PowerMockito.mock(Foo.class);
Bar bar = PowerMockito.mock(Bar.class);
MyClass sut = new MyClass(foo, bar);
sut.m2();
verify(foo).doStuff(42);
}
In the above code we have green tests for both m1
and m2
. Now we notice that there is some duplicated code in m1
and m2
: foo.doStuff(42);
. So we refactor m1
to get rid of the duplication:
public void m1() {
m2();
foo.doOtherStuff();
}
Our tests are still green after making this change, because we haven't changed the behavior of m1
; we've only changed the details of how it carries out that behavior. In order to be robust, our tests should test what we expect the SUT to do without testing how it does it.