Black box with a single entry. How to set up the skeleton?

176 views
Skip to first unread message

Rodi

unread,
Oct 25, 2011, 4:31:10 AM10/25/11
to Growing Object-Oriented Software
I am trying to set up a walking skeleton for a relatively simple
project, but have a hard time.

The application should be executed on a schedule and should get online
content (from a web service) and save it locally. That is about all it
should do and we can use the web service for our end-to-end tests
without faking it.

I've chosen to introduce a FakeScheduler to start the program. Kind of
like the ApplicationRunner in the GOOS book.

I am having difficulty finding a way to verify that it does what it
should. I have a requirement that says the local content should have
the same number of items as the online content after the program has
run. That means I should somehow count the online items and the local
items; should I set up special test classes that query the local and
online content stores? Should I query (classes not yet written in) the
program itself?

It sounds as I am testing some kind of state more than I should, but
struggle finding the behaviour I should be testing.

There is only one entry as it looks to me and that is the entry into
the program. In GOOS the walking skeleton has the entry of the
application and the Fake Auction to test the behaviour across the
system and it's boundaries. Should I set up test classes to verify the
behaviour at all boundaries, like the local store and the web service,
or more precisely the adapters that will connect the ports of those
boundaries?

Or just tell me I'm doing it all wrong and hopefully try to push me in
the right direction.

David Peterson

unread,
Oct 25, 2011, 5:17:56 AM10/25/11
to growing-object-o...@googlegroups.com
I always have a hard time getting the walking skeleton up too. It's the worst bit of GOOS.

Is the web service something that you have full control over? (i.e. you control its API, its up-time, the results it returns etc). If not, you should think about using a Simplicator as an intermediary instead of calling the web service directly. This will let your system tests provide a fake version of the web service that returns known sets of results (or errors or whatever you want).

As a general rule of thumb, avoid building tests on top of data that can change. For the tests to work, they need to know the right answer and that's a hell of a lot easier if the data doesn't change.

For the tests of the real implementation of the simplicator (i.e. the version that actually calls the webservice), you will probably have to write tests that cope with changing data, but with the simplicator you should be able to keep those kinds of tests to a minimum.

Regards,
David

David Peterson

unread,
Oct 25, 2011, 5:32:38 AM10/25/11
to growing-object-o...@googlegroups.com
This is Nat's blog entry about Simplicators - http://www.natpryce.com/articles/000785.html

Regards,
David
---

Rodi

unread,
Oct 25, 2011, 5:55:05 AM10/25/11
to Growing Object-Oriented Software
Thank you. Will read Nat's blog post too.

I thought we should try and hook up as many things as possible as soon
as possible (well actually this could be nuanced a bit better). In
GOOS the main argument for using a fake auction was that it would cost
too much money to use the real (test) auction service, although they
would have preferred to use it fro, the start and would really try to
hook it up as soon as possible.

With my project, I can use the real web service for free, so I thought
I should use it from the start.

Indeed we do not control the web service so we cannot control the
exact output or API, but I guess it's a good thing the end-to-end
tests will alert us of any (unexpected or unannounced) changes have
occured.

I have no interest in testing the content of the output, just that I
got it and stored it locally somewhere. Still not sure about how to
test that.


Will read the post right after writing this, but I guess the
simplicator is the only way to test the behaviour of the boundary
classes (adapters) in an end-to-end test.

What if they could have used the real auction in GOOS for the tests.
How would they test/implement things like
auction.hasReceivedJoinRequestFromSniper()?

On Oct 25, 11:17 am, David Peterson <peters...@gmail.com> wrote:
> I always have a hard time getting the walking skeleton up too. It's the
> worst bit of GOOS.
>
> Is the web service something that you have full control over? (i.e. you
> control its API, its up-time, the results it returns etc). If not, you
> should think about using a Simplicator as an intermediary instead of calling
> the web service directly. This will let your system tests provide a fake
> version of the web service that returns known sets of results (or errors or
> whatever you want).
>
> As a general rule of thumb, avoid building tests on top of data that can
> change. For the tests to work, they need to know the right answer and that's
> a hell of a lot easier if the data doesn't change.
>
> For the tests of the real implementation of the simplicator (i.e. the
> version that actually calls the webservice), you will probably have to write
> tests that cope with changing data, but with the simplicator you should be
> able to keep those kinds of tests to a minimum.
>
> Regards,
> David
>
> > the right direction.- Hide quoted text -
>
> - Show quoted text -

David Peterson

unread,
Oct 25, 2011, 6:10:39 AM10/25/11
to growing-object-o...@googlegroups.com
Yes, ideally, you want some real system tests that you can run that test the integration of everything including the real web service. These are the tests that find bugs in other people's systems, which is always fun.

But if you couple all of your system tests to the web service any breakage in service will knock out all your system tests, which may put you in a precarious position. Not having control over the web service results will also make it harder for your system tests to test edge cases and error cases.

In your application it sounds like you have minimal business logic, so maybe simplicators are overkill, I don't know.

Regards,
David

Rodi

unread,
Oct 25, 2011, 7:30:53 AM10/25/11
to Growing Object-Oriented Software
I read the post and simplicators are overkill for this project in
particular.

And I understand that it's good practice to fake external systems I
have no control over next to some tests that do use the real systems.

But what comes first?
The faked ones? This is much easier to come up with tests.
Or the real ones? Harder to write tests.


I think I can do the faked approach, so I will start there.

Then the question still stands as to how to write the tests with the
real one without using the simplicators. How and what to test for a
full integration? I just have one entry point: my main method and for
now there isn't any feedback for any user.

On Oct 25, 12:10 pm, David Peterson <peters...@gmail.com> wrote:
> Yes, ideally, you want some real system tests that you can run that test the
> integration of everything including the real web service. These are the
> tests that find bugs in other people's systems, which is always fun.
>
> But if you couple all of your system tests to the web service any breakage
> in service will knock out all your system tests, which may put you in a
> precarious position. Not having control over the web service results will
> also make it harder for your system tests to test edge cases and error
> cases.
>
> In your application it sounds like you have minimal business logic, so maybe
> simplicators are overkill, I don't know.
>
> Regards,
> David
>
> > > - Show quoted text -- Hide quoted text -

David Peterson

unread,
Oct 25, 2011, 8:13:26 AM10/25/11
to growing-object-o...@googlegroups.com
I guess the question is why isn't there any feedback for the user? We want the walking skeleton to be a sliver of the full system. What you described seems to be a subsystem. What's the business need? Where's the business logic? The user interface? etc.

Regards,
David

Rodi

unread,
Oct 25, 2011, 8:24:59 AM10/25/11
to Growing Object-Oriented Software
Thanks for all the answers so far.

I guess that is where most of the pain is coming from. It is a
subsystem. The main system is developed in Sharepoint (yes, I know)
and is being developed as Agile as possible at this moment with the
people involved. The program I am describing is a complementary
program that mostly stands on it's own. The real user feedback will
come when the content stored by this program has been brought from the
local store (database) to the user interface (sharepoint).

I just really wanted to do this part the GOOS way.

On Oct 25, 2:13 pm, David Peterson <peters...@gmail.com> wrote:
> I guess the question is why isn't there any feedback for the user? We want
> the walking skeleton to be a sliver of the full system. What you described
> seems to be a subsystem. What's the business need? Where's the business
> logic? The user interface? etc.
>
> Regards,
> David
>

Vasily Kirichenko

unread,
Oct 26, 2011, 1:08:21 AM10/26/11
to Growing Object-Oriented Software
You subsystem's end-to-end tests may be as following:

1. Create your (local) DB from scratch or reliably clean it up.
2. Run a local fake service which has same interface as the production
one.
3. Set test data for the service.
4. Run your subsystem and wait it's done its job.
5. Check than the DB contains right data (according to the step 3).
6. Repeat for all happy and edge cases.

This tests completely verify your subsystem.

In addition, you must have integration tests for the production
service (in order to be sure that the end-to-end tests run for exact
copy of the prod service):

1. Check the interface: get WSDL from the service and compare it to
the one used to build the fake service (from end-to-end tests above).
2. Check the contract: make simple calls of all the production
service's methods without verifying what they return (however, check
that they do not throw exceptions / return errors).

Rodi

unread,
Oct 27, 2011, 8:18:21 AM10/27/11
to Growing Object-Oriented Software
Thanks Vasily.
> > I just really wanted to do this part the GOOS way.- Hide quoted text -

Nat Pryce

unread,
Oct 31, 2011, 5:05:26 AM10/31/11
to growing-object-o...@googlegroups.com
I agree. A Simplicator helps one write system tests when an external
dependency has an awkward protocol that makes it hard to fake out.

In your case, it should be easy to build a fake version of the web
service, run it in an embedded HTTP server in your test and point you
system to talk to it. You can make the fake service give predictable
responses so that you have repeatable tests and give it a nice API do
that the tests are easy to read and write.

--Nat

www.natpryce.com

Giorgio Sironi

unread,
Nov 6, 2011, 10:41:32 AM11/6/11
to growing-object-o...@googlegroups.com
On Tue, Oct 25, 2011 at 11:32 AM, David Peterson <pete...@gmail.com> wrote:
This is Nat's blog entry about Simplicators - http://www.natpryce.com/articles/000785.html

What is the difference (if any) between Simplicators and an Hexagonal Architecture?


--
Giorgio Sironi
Piccolo Principe & Web Engineer
http://giorgiosironi.blogspot.com
http://twitter.com/giorgiosironi

Steve Freeman

unread,
Nov 6, 2011, 10:49:14 AM11/6/11
to growing-object-o...@googlegroups.com
On 6 Nov 2011, at 15:41, Giorgio Sironi wrote:
> On Tue, Oct 25, 2011 at 11:32 AM, David Peterson <pete...@gmail.com>wrote:
>
>> This is Nat's blog entry about Simplicators -
>> http://www.natpryce.com/articles/000785.html
>>
>
> What is the difference (if any) between Simplicators and an Hexagonal
> Architecture?

one way to look at it is that Simplicators are an implementation of a Hexagonal's Adaptor. The protocol from the application to the Simplicator is the port. The additional complexity is that it's in a separate process.

S.


Nat Pryce

unread,
Nov 7, 2011, 4:39:33 AM11/7/11
to growing-object-o...@googlegroups.com
My take...

The Hexagonal Architecture (aka Ports and Adapters) is a coarse-grain OO design pattern. It decouples the object model of the application domain from those of the technical domains. Among other benefits, this lets you write acceptance tests against the application domain model directly. The Hexagonal Architecture says nothing about distribution between processes, machines and/or organisations. It's concerned with how we structure our objects within each process.

Simplicators help with system testing when the system relies upon a service that is hard to fake out (for technical reasons) and cannot be changed to be easier to fake out (for organisational reasons). They are a way of moving the awkward protocol used by the service out of the port domains of our processes, to gateway(s) the very edge of our system.

--Nat

Luca Minudel

unread,
Nov 7, 2011, 8:11:55 AM11/7/11
to Growing Object-Oriented Software
Hei,

can we say that Simplicators and Impersonators (http://blog.rufiao.com/
2009/08/impersonator-pattern/) are basically the same concept/idea/
pattern ?

Can we also say that
- at the fine-grain level with TDD we have dependencies injected (via
interfaces) into constructors and methods
- while at the coarse-grain level with A-TDD we have external systems
injected (via ports and adapters) into the domain (or into the system
core) ?

Luca

On Nov 7, 10:39 am, Nat Pryce <nat.pr...@gmail.com> wrote:
> My take...
>
> The Hexagonal Architecture (aka Ports and Adapters) is a coarse-grain OO
> design pattern. It decouples the object model of the application domain
> from those of the technical domains. Among other benefits, this lets you
> write acceptance tests against the application domain model directly. The
> Hexagonal Architecture says nothing about distribution between processes,
> machines and/or organisations. It's concerned with how we structure our
> objects within each process.
>
> Simplicators help with system testing when the system relies upon a service
> that is hard to fake out (for technical reasons) and cannot be changed to
> be easier to fake out (for organisational reasons). They are a way of
> moving the awkward protocol used by the service out of the port domains of
> our processes, to gateway(s) the very edge of our system.
>
> --Nat
>
> www.natpryce.com
>
> On 6 Nov 2011, at 15:41, Giorgio Sironi <piccoloprincipeazzu...@gmail.com>
> wrote:

Nat Pryce

unread,
Nov 7, 2011, 8:58:25 AM11/7/11
to growing-object-o...@googlegroups.com
On 7 Nov 2011, at 13:11, Luca Minudel <luca.m...@gmail.com> wrote:
> can we say that Simplicators and Impersonators (http://blog.rufiao.com/
> 2009/08/impersonator-pattern/) are basically the same concept/idea/
> pattern ?

No.

An Impersonator provides "an implementation which mimics the exact
protocols and semantics of those environments while requiring minimal
resources and providing full control over execution and managed data."

A Simplicator is used when it is not practical to implement the protocol.

--Nat

Nat Pryce

unread,
Nov 8, 2011, 4:21:33 AM11/8/11
to growing-object-o...@googlegroups.com
On 7 Nov 2011, at 13:11, Luca Minudel <luca.m...@gmail.com> wrote:
> Can we also say that
> - at the fine-grain level with TDD we have dependencies injected (via
> interfaces) into constructors and methods
> - while at the coarse-grain level with A-TDD we have external systems
> injected (via ports and adapters) into the domain (or into the system
> core) ?

I guess so, though I don't think the word "injected" describes what is
going on or the design thinking involved.

OO design is concerned with inside vs outside. An object hides and
encapsulates its implementation details inside its boundary and
provides a messaging protocol for use by objects outside its boundary.
In the book we term this "internals vs peers" and "context
independence".

This inside vs outside thinking can apply all the way up and down.
Objects are made up of and composed into objects. Ports and Adapters
applies inside vs outside thinking at the process scale. Gateways and
Simplicators at the system scale.

The protocols change as the scale changes: function calls, event
queues, RPC, messaging, HTTP. As does the way of composing parts. But
the ideas of distinguishing between published access protocol and
internal implementation details and context independence remains
valuable.

--Nat

Luca Minudel

unread,
Nov 18, 2011, 5:55:55 PM11/18/11
to Growing Object-Oriented Software
Similarities and differences between the 2 patterns are clear to me
now.
It looks to me that the Impersonator pattern is similar to the result
of the refactoring "Skin and Wrap the API" documented in the WELC (the
signature of the server service is preserved) but applied at a system
scale.
While the Simplificator pattern is similar to the result of the
refactoring "Responsibility-Based Extraction" also documented in the
WELC (from the complicated API the responsibilities that are needed
by the client are extracted with a simplified signature) again applied
at a system scale.




Some more terminology check here.

Reading here your comments about "inside vs outside" and "internals
vs peers" and "context independence" finally I got a overall
understanding of these terms and I can map them with the term "levels
of abstractions" that I'm used to from the C++ Stroustrup's book.
From a practical point of view internals vs peers has to do with
deciding where to stub and where to mock. Right ?
And a practical example of "context independence" could be wrapping a
library behind an interface to take away the dependency to details the
class should and need not to know about. Right ?




What is not yet clear to me if from a design point of view the
distinction between the process scale and the system scale is needed/
useful.
For example .NET provide automatic proxy to call objects cross a
process boundaries. What is different in the coarse-grain of the
public interface and the communication that can be asynchronous.
Again, I'm double-checking that I'm understanding correctly what you
mean.




Luca


On Nov 8, 10:21 am, Nat Pryce <nat.pr...@gmail.com> wrote:

Steve Freeman

unread,
Nov 19, 2011, 3:51:07 AM11/19/11
to growing-object-o...@googlegroups.com
On 18 Nov 2011, at 22:55, Luca Minudel wrote:
> Reading here your comments about "inside vs outside" and "internals
> vs peers" and "context independence" finally I got a overall
> understanding of these terms and I can map them with the term "levels
> of abstractions" that I'm used to from the C++ Stroustrup's book.
> From a practical point of view internals vs peers has to do with
> deciding where to stub and where to mock. Right ?

Peers are what I stub or mock--which depends on whether it's a query or action. I tend to test internals through the containing object, with maybe some more precise direct testing of the internal object.

> And a practical example of "context independence" could be wrapping a
> library behind an interface to take away the dependency to details the
> class should and need not to know about. Right ?

yes.

> What is not yet clear to me if from a design point of view the
> distinction between the process scale and the system scale is needed/useful.
> For example .NET provide automatic proxy to call objects cross a
> process boundaries. What is different in the coarse-grain of the
> public interface and the communication that can be asynchronous.
> Again, I'm double-checking that I'm understanding correctly what you
> mean.

Not sure what the question is here. There's a famous paper about the fallacies of distributed computing that points out how we can't ignore the network.

http://en.wikipedia.org/wiki/Fallacies_of_distributed_computing_(Deutsch)

S.


Giorgio Sironi

unread,
Nov 19, 2011, 4:06:36 AM11/19/11
to growing-object-o...@googlegroups.com
I would add the 2nd paper in this list:
which explains how remote Proxy objects tend to develop an interface which does not hide remoting.

--
Giorgio Sironi

Luca Minudel

unread,
Nov 20, 2011, 7:32:40 AM11/20/11
to Growing Object-Oriented Software

On Nov 19, 9:51 am, Steve Freeman <st...@m3p.co.uk> wrote:
> On 18 Nov 2011, at 22:55, Luca Minudel wrote:
>
> > Reading here your comments about  "inside vs outside" and "internals
> > vs peers" and "context independence" finally I got a overall
> > understanding of these terms and I can map them with the term "levels
> > of abstractions" that I'm used to from the C++ Stroustrup's book.
> > From a practical point of view internals vs peers has to do with
> > deciding where to stub and where to mock. Right ?
>
> Peers are what I stub or mock--which depends on whether it's a query or action. I tend to test internals through the containing object, with maybe some more precise direct testing of the internal object.
>

Still have a doubt about the term internals.
In the example of the Receiver at page 230 of the GOOS there is the
test RejectsRequestsNotWithinTheSameDay() where the object Clock is
considered an internal of Receiver (... we’ve made it obvious that
Receiver is dependent on time—we can’t even create one without a
Clock. Some argue that this is breaking encapsulation by exposing the
internals of a Receiver...) and the test Clock is stubbed.
If I got it right sometime internals like Clock can also be stubbed,
but never mocked.


> ...


>
> Not sure what the question is here. There's a famous paper about the fallacies of distributed computing that points out how we can't ignore the network.
>
> http://en.wikipedia.org/wiki/Fallacies_of_distributed_computing_(Deutsch)

Thanks, also to Giorgio for the interesting links!
I see the point here and I recognize the differences between local and
remote objects and interfaces.

When I look at the hexagonal architecture pattern it seams to me that
the pattern make sense also when adapters and ports are at the system
level, not just at the process level.

Nat Pryce

unread,
Nov 20, 2011, 3:59:50 PM11/20/11
to growing-object-o...@googlegroups.com
On 20 November 2011 12:32, Luca Minudel <luca.m...@gmail.com> wrote:
> Still have a doubt about the term internals.
> In the example of the Receiver  at page 230 of the GOOS there is the
> test RejectsRequestsNotWithinTheSameDay() where the object Clock is
> considered an internal of Receiver (... we’ve made it obvious that
> Receiver is dependent on time—we can’t even create one without a
> Clock. Some argue that this is breaking encapsulation by exposing the
> internals of a Receiver...) and the test Clock is stubbed.
> If I got it right sometime internals like Clock can also be stubbed,
> but never mocked.

The Clock exists outside (and before) the Receiver and is passed to
the Receiver when the Receiver is constructed. Therefore it is NOT an
internal of the Receiver. It is a peer of the Receiver.

"Internals" are internal implementation details that are not visible
from outside an object that uses them. From outside the object,
there's no way of telling what internals exist, how they are
constructed or used, what their lifetimes are, etc. Therefore they
cannot be mocked or stubbed. Client code cannot rely on them, and so
does not break when they are changed (loose coupling).

--Nat

--
http://www.natpryce.com

Luca Minudel

unread,
Nov 26, 2011, 11:11:16 AM11/26/11
to Growing Object-Oriented Software
The sentence "Some argue that this is breaking encapsulation by
exposing the *internals* of a Receiver" tricked me a little to think
the book were considering the Clock an Internal and not a Peer of
Receiver.

Now think I got the definitions used in the goos for Peer and
Internals, probably I should collect the info/definition from this
thread and write it somewhere.

Personally when I code I also see objects that are in between of
Internal and Peer:
- like an Internal they share the lifetime of the containing object
(like Receiver in the book example), they are used only by the
containing object, they are not exposed in any way in the public
interface of the containing object (as property, parameter type or
return type of some public member)
- like an Internal, a different implementation of the containing
object could not make use at all of that "internal" object or could
use a completely different one
- like a Peer they are injected into the container object throw the
parametric constructor (like Clock in the book example)

One situation where I end up with that kind of object is when the
containing object do not have/need to know the details/info that are
needed to instantiate that "internal" object. So I inject it and I
delegate the instantiation to someone else.


Does this make sense ?
How would you call/classify this kind of objects ?

Luca


On Nov 20, 9:59 pm, Nat Pryce <nat.pr...@gmail.com> wrote:

Uberto Barbini

unread,
Nov 27, 2011, 11:03:35 AM11/27/11
to growing-object-o...@googlegroups.com

Sorry Luca but I lost you, can you do an example? From what you wrote
you're describing the Peer to me.

The Clock can be reused in many other objects of different classes
that need to read the time and it's not given that will die together
with the Receiver.


Uberto

Luca Minudel

unread,
Nov 27, 2011, 4:39:05 PM11/27/11
to Growing Object-Oriented Software
Hola Uberto,

I mentioned Clock and Receiver as example to clarify things ... but
the example made the sentence more confuse :D

Indeed I was not talking about the Clock that is a Peer as you pointed
out, nor I'm talking about the Receiver.
Instead I was talking about a kind of object that is not exactly a
Peer and neither an Internal as defined by Goos because
- have 2 of the characteristics of an Internal (same lifetime or less
of his container, is an internal implementation detail that can vary
for different implementation strategies)
- have 1 characteristic of a Peer (is injected in the containing
object through the constructor).


Let's try with an example.
Think about and object GameController that execute a user command and
to do this needs to retrieve info about user preferences, the object
that retrieve the user preference is called ... UserPreferences
UserPreferences is used only by the GameController, every instance of
GameController have it's own instance of UserPreferences that can be
disposed together with the GameController. And UserPreferences is not
exposed by GameController in any way in the public interface. Here
UserPreferences looks to be an Internal of UserPreferences.

UserPreferences can have different implementations, can retrieve info
from a Cookie, from a file in the file-system, from and Oracle db or
from a SqlServer db.
For the cookie it need to know the cookie name, for the file-system it
need to know the path with the filemane, and for the DBs it need to
know their connection strings that differs between Oracle and
SqlServer.

The decision of with concrete implementation of UserPreferences to use
is not made by GameController, is made elsewhere. GameController just
need to use it.
So GameController don't have/need to know about the cookie name or the
file path or the connection string. That's why this knowledge is
elsewhere and so UserPreferences is instantiated and injected into
GameController through the parametric constructor. Internals are not
injected via the constructor, so here UserPreferences looks to be a
Peer.


Do you agree that UserPreferences is not exactly a Peer as defined in
the goos and it neither an Internal as defined in the goos ?
How would you call/classify this kind of objects then ?

Luca

On Nov 27, 5:03 pm, Uberto Barbini <ube...@ubiland.net> wrote:

Nat Pryce

unread,
Nov 27, 2011, 5:44:02 PM11/27/11
to growing-object-o...@googlegroups.com
That sounds like what we call an "adjustment" in the book.

--Nat
--
http://www.natpryce.com

isaiah perumalla

unread,
Nov 27, 2011, 6:02:21 PM11/27/11
to growing-object-o...@googlegroups.com
To me if the collaborating object is  exposed via the public api (ie either passed in through the constructor or public method) then its not an internal. It is peer, this could be a policy object or a dependency depending on the domain.  “A composite object should be simpler than the sum of its parts" i use this as a heuristic to follow when deciding what should be internal to an object and On the other hand we should ensure we are not hiding the wrong information inside an object. Well-designed objects should be context independent and not tied to its environment.
--
Isaiah Perumalla

Luca Minudel

unread,
Nov 29, 2011, 10:00:34 AM11/29/11
to Growing Object-Oriented Software

The extra distinction that I make here is for UserPreferences and for
these objects that are even more clearly implementation details (I
recognize, UserPreferences looks a lot a "adjustment" as described in
the book, was not a great example from me) and still are passed as
parameters in the constructor.
This distinction remind me a similar distinction between the
constructor and the public interface of an object (in the same way
Java and C# interfaces cannot specify a constructor nor C# Java C++
allow to inherit a constructor) .
It is interesting that as Isaiah wrote "exposed via the public api (ie
either passed in through the constructor or public method)" so looks
like this is a different opinion.


This distinction is useful to me because I find advantages in not
mocking these objects that are implementation details (even when
passed in through the constructor) :
- I find more interesting to describe with mocks in the unit tests the
interaction between object peers at a level higher then low level
implementation details
- I find more practical to stub these objects because the interaction
with these objects is more subject to unimportant changes: with a stub
the test have more chases not to fail after the changes while a mock
will likely fail even when there is no bug nor a behaviour change that
I'm interested to describe in a test (with stubs the expected
behaviour is tested throw the containing object)

To rephrase it, I find this distinction useful in order to identify
some of the objects that is preferable to stub them instead of mock
them because the interactions with those objects is not a useful focus
for a unit test.

I guess that you use other ways/criteria for this or you use a
different approach. If you have link, can point me to some paragraph
of the book or if you can tell, I'm curious to know.

Luca

isaiah perumalla

unread,
Nov 29, 2011, 11:13:11 AM11/29/11
to growing-object-o...@googlegroups.com
Maybe this is bit of a simplistic view but to me if you are passing it in via the public api then it cant be an internal, to me internals are objects hidden inside and are not visible to clients via the public api, in your example  Userpreference  to me this is a peer as it would be inappropriate to hide this inside the object as it could depend on external environment such at filesystem or db  it would not context independent. 
"I find advantages in not
mocking these objects that are implementation details (even when
passed in through the constructor) :..."
The way I think about this, is that messages send to collaborator that cause side effects and message sends which are queries asking for info. not every thing passed via constructor needs to be mocked, we could pass in fake or stub as you mentioned, as they usually tend to be queries that are idempotent . But if any of the messages send to the collaborators cause side effect then it makes sense to verify these messages via mocks
--
Isaiah Perumalla

Luca Minudel

unread,
Nov 29, 2011, 3:27:43 PM11/29/11
to Growing Object-Oriented Software

On Nov 29, 5:13 pm, isaiah perumalla <isaiahperuma...@googlemail.com>
wrote:


> Maybe this is bit of a simplistic view but to me if you are passing it in
> via the public api then it cant be an internal, to me internals are objects
> hidden inside and are not visible to clients via the public api, in your
> example  Userpreference  to me this is a peer as it would be inappropriate
> to hide this inside the object as it could depend on external environment
> such at filesystem or db  it would not context independent.

We agree on this , it is a Peer as described in the goos book.


> "I find advantages in not
> mocking these objects that are implementation details (even when
> passed in through the constructor) :..."
> The way I think about this, is that messages send to collaborator that
> cause side effects and message sends which are queries asking for info. not
> every thing passed via constructor needs to be mocked, we could pass in
> fake or stub as you mentioned, as they usually tend to be queries that are
> idempotent . But if any of the messages send to the collaborators cause
> side effect then it makes sense to verify these messages via mocks
>

When the contained object receive a message and there is a side effect
on it (and not on the containing object) I usually end up testing it
with a mock too.
So looks like here we are doing in similar ways.

When we are interested into that side effect on the contained object,
looks like the containing object have a responsibility toward the
contained object.
In this case I will not call the contained object an implementation
detail but more like a Peer (so yes, mocking is an option here).


In the end, the distinction I'm doing for the objects that are
implementation details and still passed to the constructor, is to
define criteria to decide where is better to mock and where to stub
(when there is a choice of course:)


Luca

Uberto Barbini

unread,
Nov 30, 2011, 5:50:43 AM11/30/11
to growing-object-o...@googlegroups.com
hi Luca

> When the contained object receive a message and there is a side effect
> on it (and not on the containing object) I usually end up testing it
> with a mock too.

ok this is a "real" peer.

but when there is no side effect on the contained, like in your
example, I think you can simply pass an immutable value object
(configuration in your case).
That's why you prefer to stub them during testing.

In case of Decorator and Strategy peers, I prefer to test them using mocks.

Those

Uberto

Reply all
Reply to author
Forward
0 new messages