Partial Mocking As Code Smell?
Why is there so much hating going on about 'partial mocking' and the code that requires it?
Here's an (theoretical) example implementation:
public ComplexResult1 operationA(Stimulus a) {
{
...
result = ...;
}
auditTheChange(a);
}
public ComplexResult2 operationB(Stimulus b) {
{
...
result = ...;
}
auditTheChange(b);
return result;
}
void auditTheChange(Stimulus stim) {
// do a bunch of stuff to record the change
// and interact with another outside service
}
Now, in my understanding this is well refactored code.
If I want to UNIT test operationA and operationB, and ensure that auditing happens in each scenario, but with开发者_开发问答out having to test the specifics of the audit code, I would use partial mocking.
What am I not seeing/understanding that causes so many projects (EasyMock, Mockito, etc.) to recommend refactoring?
If auditing is truly an internal function of the class then the code should be tested as part of the unit test. Why does your class handle both complex operations and auditing? Could the auditing be moved to a separate class?
If so, introduce the auditing as a collaborator with this class and mock it out. If not, unit test it.
You can use partial mocks, but in this case I think it is an indication the class is doing too much.
If auditTheChange
is a private function, then you just don't write a test which verifies its invocation.
You don't want your unit test be tightly coupled to an implementation.
And just in general: Don't unit test private methods.
The key point is "what is the unit being tested".
A lot of developers think OO. In OO, "object" is the unit of software so that object is also the unit that is tested in the unit test. In your example, auditTheChange() is a private method in an object. A unit test should focus on the behavior of public method only. Mock a private method means the unit test case dealing with some implementation detail of the unit which is considered as a "code smell".
Some developers think the unit of software is "method". In your example, you do think in this way. Because operationA and operationB is too complicated so that you create auditTheChange so that the complexity of unit operationA and operationB can be reduced. If you think in this way, partial mocking is not a "code smell" because the method is a unit being tested and mocking a private method also means "focus on behavior, not implementation details".
There is no absolute right or wrong here. It really depends on the nature of your project or team. I worked for a company developing an enterprise info system using Spring. In Spring, almost all business logic is implemented in xxxService objects. When a method is too complicated, we just move some logic to a private method as you did in your example. If we always move that logic to a new class, there will be a lot of classes and objects will be created and that will make the programs difficult to maintain. So, we just moved the logic to private methods and used partial mocks. Actually, a lot of people needed partial mocks. You can check this Mockito document. At the beginning, mockito thinks partial mock is a code smell. After a long discussion and debate, they also support partial mocks now.
精彩评论