Mocking frameworks are good for testing a system by mocking that system's dependencies; you wouldn't use a mocking framework to mock or stub add
if you are testing add
. Let's break this out a bit further:
Testing add
A mocking framework is not good for testing your add
method above. There are no dependencies other than the very stable and extremely-well-tested JVM and JRE.
public int add(int a, int b) {return a+b}
However, it might be good for testing your add method if it were to interact with another object like this:
public int add(int a, int b, AdditionLogger additionLogger) {
int total = a + b;
additionLogger.log(a, b, total);
return total;
}
If AdditionLogger isn't written yet, or if it's written to communicate with a real server or other external process, then a mocking framework would absolutely be useful: it would help you come up with a fake implementation of AdditionLogger so you could test your real method's interactions with it.
@Test public void yourTest() {
assertEquals(5, yourObject.add(2, 3, mockAdditionLogger));
verify(mockAdditionLogger).log(2, 3, 5);
}
Testing add
's consumers
Coincidentally, a mocking framework is also unlikely to be good for testing consumers of your method above. After all, there is nothing particularly dangerous about a call to add
, so assuming it exists you can probably call the real one in an external test. 2 + 3 will always equal 5, and there are no side effects from your calculation, so there's very little to be gained by mocking or verifying.
However, let's give your object another method that adds two numbers with a little bit of random noise:
public int addWithNoise(int a, int b) {
int offset = new Random().nextInt(11) - 5; // range: [-5, 5]
int total = a + b + offset;
return total;
}
With this, it may be very hard for you to write a robust assert
-style test against this method; after all, the result is going to be somewhat random! Instead, to make an assert
-style test easier, maybe we can stub out addWithNoise
to make some of this more predictable.
@Test public void yourTest() {
when(yourObjectMock.addWithNoise(2, 3)).thenReturn(6);
// You're not asserting/verifying the action you stub, you're making the dependency
// *fast and reliable* so you can check the logic of *the real method you're testing*.
assertEquals(600, systemUnderTestThatConsumesYourObject.doThing(yourObjectMock));
}
In summary
It can be easier to explain mocking and mock syntax when interacting with well-known operations like add
or well-known interfaces like List
, but those examples are not usually realistic cases where mocks are needed. Remember that mocking is only really useful for simulating the dependencies around your system-under-test when you can't use real ones.