TDD and Mockito testing newb here... I have recently discovered about injection of mocks of private fields and am trying to get my ideas straight.
It may well be that my thinking on this particular matter is all wrong, but it's just that I often find a situation where I want to test that calling a particular method has resulted in a private field being assigned: before the call it was null
, and after the call it is set to an instance of whatever class.
A mocked private field is a subclass of the class in question by the time you start to run your test method, so obviously testing for null
is meaningless/doesn't work. Equally, if your method results in an assignment of this field this means that the mock variable has been replaced by a genuine instance. Thus, even if methods are called on it it won't lead to any interaction with the mock variable. In any event, if the test is just to check on the creation and assignment there is no reason you would want to have any interaction with it in the test.
Obviously one answer is to create a public
get()
method or a public
create()
method in the app class. But this gives me a bad feeling as it is clearly just being done for testing purposes.
Incidentally there will be those, many no doubt much more experienced than me at TDD, who will say that I'm getting too fine-grained and shouldn't be testing something as specific as assignment of a field. But my understanding of the most extreme approach to TDD is "don't write a line of code without a test". I really am trying to stick with this at this stage as far as possible. With experience maybe I will have greater understanding of how and when to depart from this principle.
It's just that assignment of a field seems to me to be a "class event" (of the host class) as worthy as any other type of event, such as a call of a method on the field once an instance has been assigned to the field. Shouldn't we be able to test for it in some way...? What do the Mockito pros who accept that this may be a legitimate thing to test for do in these circumstances?
later...
The comment from Fabio highlights the tension which, as a newb, I find puzzling, between "never write a line without a test" and "test only public methods": the effect of this is inevitably to expose much more stuff than I want, purely for the sake of testing.
And what he says about "changing tests all the time" I also find problematic: if we inject mocked private fields, and use them, then we are going to have to change the tests if we change the "implementation details". Nor does this idea fill me with dread: a need for change is perceived, you look at the very explanatory names of your existing test methods and decide which ones no longer apply, and of course you create new ones... the testing code, like the app code, will have to change all the time, right?
Isn't the testing code like some sort of die or mould, which guides and constrains the app code but at the same time can be detached from it? By Mockito allowing us to mock private fields a privileged form of access is already granted... who's to say how far this privileged access should rightly extend?
even later...
Jeff Bowman suggests this is a dup with this. I'm not entirely convinced, since I am asking a very specific thing for which it's just possibly there may be a specific answer (some Mockito means of detecting assignment). But his answer there seems very comprehensive and I'm trying to fully understand it all... including the whole dependency injection thing... and the compromises you seem have to make in "distorting" your public interface to make an app class as testable as you want to make it.