Hey dude, what are the differences between acceptance tests and unit tests?
Well, an acceptance test – aka scenario test – may involve many units of our software, while a unit test is a test for only one unit.
What if the acceptance test involves only one unit? Now the acceptance test and the unit test are the same?
Who usually write acceptance tests?
Who usually write unit tests?
Of course, developers!
You see the difference?
Yeah, customers don’t have any idea about the internal structure/logic of the software, so they write tests that are black box tests. Developers, on the other hand, write white box tests. Aha, black box and white box are keywords of the difference.
Yes, that’s right! In other words, acceptance tests aim to assert that a problem was solved correctly, whereas unit tests aim to assert that a solution was implemented correctly.
How many test cases are enough for a test?
It depends. In an acceptance test, the list of test cases should express the user requirements fully, clearly and unambiguously. In a unit test, the test cases should cover all the code flows of the unit being tested, two test cases that execute the same code flow are considered to be identical, but they are still useful as they increase confidence. Therefore, in many situations, from the perspective of a developer, you may see some test cases of the acceptance test are redundant, because you already know how the unit is implemented.
I’ve heard about mocks sometimes, what are mocks?
Mocks are special objects used for unit tests only. Indeed, there are unit tests in which it’s very difficult to make a certain code flow be executed e.g. a code flow that depends on something random/slow/frustrating from database, network … In those cases, we need to create one or many mock objects that fake the behaviors of database, network … and inject them into the object being tested.
OK, so our code base will have extra classes called mocks, do we need to test the mocks themselves?
No, testing mocks doesn’t make sense because their logic are quite trivial and thus should work correctly. Don’t test everything, do test things that are in doubt only. But your question reminds me another case of using mocks: things that are in doubt (e.g. in development, not tested yet …) should be mocked also. The only doubtful thing in a unit test is the unit itself, everything else must be clear and correct. Remember, in a unit test, we are testing behaviors of the current unit, not behaviors of its friends. The more isolated a unit test is, the better it is.
A moment ago you said that we use mocks by injecting them into the object being tested. Is this injecting possible in every case? You know, there are cases in which the code that need to be mocked is actually a call to a static method or creating a new object instance. These things are very concrete, how can you mock them?
In those cases, you should consider carefully whether the mocking is necessary or not, as discussed. I mean, if that static method / concrete object is stable, well tested, and facile; then no need to mock. But if you really want to mock, no way! In general, static methods should be restricted, creating new concrete objects should be the responsibility of factories. And factories can be easily mocked too.