Reputation:
I'm testing a function that takes several paramters and on the basis of their values calls different private methods.
I want to check that the function always call the right private method.
Since I know what the private methods will do I can check the final result but it would be more convenient to be able to check directly if the right function was called, because I have already tested the private methods.
Is there a way to replace a privae method with a stub?
Upvotes: 0
Views: 609
Reputation: 81074
Yes, there are mocking libraries that let you do this. One is PowerMock. From their private method tutorial, you need something like this:
@RunWith(PowerMockRunner.class)
@PrepareForTest(MyUnit.class)
public class TestMyUnit {
@Test
public void testSomething() {
MyUnit unit = PowerMock.createPartialMock(MyUnit.class, "methodNameToStub");
PowerMock.expectPrivate(unit, "methodNameToStub", param1).andReturn(retVal);
EasyMock.replay(unit);
unit.publicMethod(param1);
EasyMock.verify(unit);
}
}
However, I really disagree with this practice myself. Your unit test should test inputs, outputs, and side effects, and that's it. By ensuring that a private method is called correctly, all you're doing is preventing your code from being easily refactored.
In other words, what if down the road you want to change how your unit does its job? The safe way to do this is to make sure the code is under (passing) tests, then refactor the code (potentially including changing which internal methods are called), and then run the tests again to make sure you didn't break anything. With your approach, this is impossible because your tests test the exact implementation, not the behaviour of the unit itself. Refactoring will almost always break the test, so how much benefit is the test really giving you?
Most often you would want to do this because you're actually considering those privates a unit unto themselves (this sound like you, since you say you are testing those private methods directly already!). If that's the case, it's best to extract that logic into its own class, test it, and then in the remaining code interact with a mock/stub version of that new unit. If you do that, your code has a better structure and you don't need to fall back on the voodoo magic that is PowerMock. A fantastic reference to do these kinds of refactorings is Michael Feathers' Working Effectively with Legacy Code.
Upvotes: 2
Reputation: 20837
Code coverage tools do this kind of thing by re-writing the bytecode before the tests are actually run. So, it's got to be possible, but it's non-trivial.
Update: writing a unit test that requires that the "right" private method be called kind of makes the job of refactoring a real pain because then you have to re-write all your tests. That kind of defeats the purpose of the tests.
Upvotes: 0
Reputation: 402
If calling the right "private method" has no observable outside result, are you sure you want to test this? Maybe shouldn't.
If the end result is the same regardless of whether the private method gets called, and you still want to observe its invocation, you could make the method public and move it to its own class, and mock that class. Then you could verify (using Mockito or a similar framework) whether your method is being called.
Upvotes: 0
Reputation: 763
Would it be possible to provide the class in question with another object, to which the private methods are moved and made public? In that case, it would be easy to create a test dummy for that interface.
Upvotes: 0
Reputation: 2228
As one of solution can be used proxy from inner classes. You need add inner class inside every your class which must be tested. But it is not very good solution for big product project. its require create addition script for remove generated classes from your release files(jar/war).
But more easier way will be used PowerMock as wrote in comments bellow(or upper :)) - http://code.google.com/p/powermock/wiki/MockPrivate
Upvotes: 0