Re: Re: Single assert / Single mock rule in practice

Angel Java Lopez <[email protected]> Fri, 17 Jan 2014 08:25:39 -0200
Newsgroups gmane.comp.programming.test-driven-development
Message-ID <CAMs+Dq+uxjv+BEonk8n47VULnAnmUM3E9AR8f=DviZKXzDdHqg@mail.gmail.com>
Interesting thread!

Regarding
def exists(item_id):
    xdep.open()  # opens some remote resource

    item = xdep.get_item(item_id)
    xdep.close()
    if item:
        return item.id == item_id
    else:
        return false

I usually write a xdep alternative implementation. I don't call it a mock,
because is an implementation of the same service, but local. And I use it
even in the final application (for first iteration, for demo purpose). You
can build it using TDD, and then, inject it to the exists() test. It has no
additional method like "expected" nor other mockist methods.

In a non-public project, my team was building system A, that should call
already existing system B (a REST API). Instead of struggling with test
that directly call the REST API, we implemented a local C1 library, that
provides all the service needed by A. That is:

A -> C1 and C1 works locally

Then, we write a C2 library that real calls the system B, using TDD:

C2 -> B

With A -> C1 we could build a lot of use cases, without network connection,
REST API server running, etc, in an agile way.
Only in C2 -> B we needed such environment. Then, one day, we switched to

A -> C2 -> B

and voila! Practically all use cases were working.

But all C1 was not one or more mocks, it was an alternative and working
implementaiton, in-memory.

Angel "Java" Lopez
@ajlopez






On Fri, Jan 17, 2014 at 6:36 AM, Mateusz Łoskot <[email protected]> wrote:

>
>
>
> On 15 January 2014 20:08, Adam Sroka <[email protected]> wrote:
>
>> On Wed, Jan 15, 2014 at 12:56 PM, Mateusz Łoskot <[email protected]>wrote:
>>
>>>  On 15 January 2014 04:41, Adam Sroka <[email protected]> wrote:
>>>
>>>> On Tue, Jan 14, 2014 at 5:31 PM, Mateusz Łoskot <[email protected]>wrote:
>>>>
>>>>>
>>>>> Isn't a unit test somewhat tightly coupled to implementation?
>>>>>
>>>>>
>>>> Yes, by definition, because you are testing the way the "unit" works.
>>>> It is necessarily coupled to the interface of the object you are testing,
>>>> though not necessarily to its internals. If the test is coupled to the
>>>> internals of the object that is a failure of encapsulation and there is
>>>> probably a detectable code smell.
>>>>
>>>
>>> Yes, that is waht a general theory of (unit) testing says, but...devil's
>>> in the detail like
>>> classicists vs mockists (
>>> http://martinfowler.com/articles/mocksArentStubs.html)
>>> I mean, lots of things about unit teststing makes a perfect common sense
>>> and is obvious... from high altitude,
>>> but practice seems to be much more complex.
>>>
>>>
>>>
>> It gets easier over time if you practice merciless refactoring. The
>> problem is that most programmers don't. They change stuff when it is
>> obvious and makes their lives immediately easier and defer it otherwise.
>> Then it turns into a mess and they no longer know how to fix it easily.
>> [...]
>>
>
> Adam,
>
> I see your point, although it does not mean I immediately see where to
> plug it in my practice.
>
>
>> When and whether to use mocks is more a matter of style than anything
>> else, and philosophical debates about it are mostly a waste of time.
>>
>
>
> I do not mean to start any such debate, no.
>
> I am learning from many resources what you are saying, when/if to mock is
> matter of style and I have no reason to not to trust it is.
>
> But, as soon as I get back to practising UT
> and I have an external dependency, i.e. remote service, mocking an obvious
> choice
> otherwise I can't see how I can continue testing my unit without either
> integrating
> with real remote service or mocking it.
> Then I remember "mocking is matter of style" and I get confused
> immediately:
> does it mean I either test my unit with mocking or not test at all?
>
> I hope you can trace the tracks of my thinking here.
>
> The a self-contained complete example I posted in which I'm
> trying to test xdep as external legacy, uses code
> beyond my control. I can't change how xdep is designed.
>
> Let's try to simply it to get away from conceptual discussion on
> techniques and methods, and get down to bare code:
>
> def exists(item_id):
>     xdep.open()  # opens some remote resource
>
>     item = xdep.get_item(item_id)
>     xdep.close()
>     if item:
>         return item.id == item_id
>     else:
>         return false
>
> Given id of an existing item,
> When I call exists()
> Then it reports item does exists (return True)
>
> How would you test such function?
>
> 1. Mock the whole xdep (and set up all 3 functions as necessary for the
> scenario above).
> 2. Pick most relevant xdep function, namely the xdep.get_item and mock it?
> 3. No mocking at all? Then, how would you unit test exists function?
>
> Best regards,
> --
> Mateusz  Łoskot, http://mateusz.loskot.net
>
>  
>