choose the right tool for the task in hand. My phrasing didn't get right. :)
https://cleancoders.com/videos/java-case-study. And besides that, that's
they didn't need a 'real' database at all. Extra advice: if you have time
design/test your application (I'm studying about it now).
Post by Dariusz Gafka@Israel
Is Uncle Bob really using in memory implementations for unit testing?
This is really weird thing to me, because in my opinion unit tests are not
place for in memory implementations. I use them for acceptance tests only
written in gherkin.
@Matteo
"When mocks get in the way of refactoring, it usually happens because I'm
mocking an interface that is not a good abstraction for the domain"
Do you mean, that when we find correct abstraction for the domain, we will
no need to change interaction between two objects while refactoring?
What about situation when the abstraction is correct, but we would like to
delegate it to some other place (it will break the tests)?
I would love to see some of your code examples with tests, to better
understand your way of thinking.
W dniu czwartek, 27 października 2016 11:56:38 UTC+2 uŌytkownik Matteo
Hi Israel,
IMO it's not a matter of "choosing a path" between using mocks or not
using them. They are one tool out of several.
Usually I start with the business requirements, and list the tests that I
think are needed to meet those requirements. Then I write the first test
and start the TDD process. In the course of doing this, I write more
tests, and sometimes I find that some tests are too hard to write, or too
hard to pass. Then I have to think and probably change the design. The
style of test that I use depends on the context. I always try to make the
test tell a story about what I'm trying to do. Sometimes mocks help me do
that, sometimes I use other techniques.
When mocks get in the way of refactoring, it usually happens because I'm
mocking an interface that is not a good abstraction for the domain. You
should not expect to find the right abstractions easily! It generally
takes more than one try. Once you have found a good abstraction, it tends
to be stable. It may help to live with duplication for some time before
you start abstracting.
Hope this helps!
Matteo
@Darius
Now I got your point. From my experience: If you choose the path of
Mocking/Interaction testing, you can't avoid this kind of coupling with the
test implementation, In this case you may use this over-constraining as an
advantage to check if your test is being to hard to build (in that case
about, indeed can be a dangerous thing, but it could no too (vague answer.
http://youtu.be/ty3p5VDcoOI
To have the advantage to really be able to refactor freely (besides
changes in the constructor), only with the Classist Approach of using the
real implementation on an alternate in-memory implementation (like Uncle
Bob does). But this path come with it's own 'problems': fixtures that can
be are hard to setup, maintaining another implementation of your
collaborators (like an ProductRepositoryInMemory) and being a harder to
implement you app in a top-bottom fashion.
I spent lot of time doing both and in the end I think it's matter of
taste, you have to choose the technique that fits your 'way of programming'
@Matteo
After some time of thinking, you're right in here. I came with the
solution first even that I wrote the tests first. I know, that is not way
to do it, but the experience and habits are just strong. When I start to
thinking of some problem, my brain tries to find solution immediately.
So "Let the tests guide you." isn't so simple, like it sounds. :)
You are right, "Let the tests guide you" is not easy! You may at first
treat it like a game with simple rules: don't write more code than is
needed to pass hte test. Focus on the process, not on your deadline. It may
be easier to do that on a kata rather than on real work :)
http://online-training.jbrains.ca/p/wbitdd-01
Matteo
W dniu Åroda, 26 października 2016 23:29:10 UTC+2 uÅŒytkownik Israel
Round 2 :)
1.a Maybe I didn't get it right, but if you use a real instance it won't
solve the problem of having to change all the tests in the case that you
figure out that you don't need the factory anymore. When you say: "my
tests will depend on existence of it" as a bad thing, I don't agree. You
are testing a class that depends on another collaborators and makes sense
to the test express this necessity somehow (you have to give a
real/fake/stub/mock implementation to it). By having to handle this
dependency in your test, the test is also giving some feedback about your
design (when you happen to have 5+ collaborators you will think "man,
there's something wrong in here").
2. In that case, yes, I would create a test to check if my TransactionService
handles the failure accordingly (write some log file), and for that I would
stub the collaborator to throw an exception and check the logging (and yes,
It'll be like a repeated test, but one case if for identifying an error and
the other is about how to handle the error).
https://vimeo.com/80533536
Hi Dariusz,
this example code does not seem to do much, now, does it? Perhaps the
only interesting thing that happens here is in the getFor() method, which
you didn't show. This looks to me like you came up with a solution, and
you're now trying to write tests that prove that your solution exists.
Good tests (IMO) are tests that talk about specific cases of business
things that are interesting to your customer.
A better approach (in my opinion) is to start with a blank slate: forget
about the TransactionProvider and the TransactionProviderFactory
altogether. Write a test that
How about you start with a test of what interesting things happen, from
the point of view of the business, when someone calls
transfer(new Money(1), "whatever")
Try to solve it in the simplest possible way, then proceed with the next
variation of
transfer(X, Y)
that makes sense to the business. Don't write more code than is required
to pass the tests. Let the tests guide you.
Hope this helps,
Matteo
Hello,
I am strugling with one problem about testing public interface only.
I think the best explanation will be, if I start with example. So here we
go :)
We are having
public class TransactionService {
private TransactionProviderFactory transactionProviderFactory;
TransactionService(TransactionProviderFactory
transactionProviderFactory) {
this.transactionProviderFactory = transactionProviderFactory;
}
public void transfer(Money money, String type)
{
transactionProvider =
this.transactionProviderFactory.getFor(type);
transactionProvider.startTransaction(money);
}
}
class TransactionProviderFactory {
TransactionProvider getFor(String type) {
//returns for type
}
}
Now let's say they both belongs to the same package.
1. I should test only TransactionService as it's the only API, that is
exposed in this package. Other packages should only talk to
TransactionService, not other class in this package.
But now constructing TransactionService for tests requires
TransactionProviderFactory, which I shouldn't know about, because it's
internal to the package.
How should I handle it?
Should I mock it or create real instance and inject or maybe do something
else with it?
2. The TransactionProviderFactory contains logic also.
It should be tested against returning correct Provider for specific type.
It should be tested for throwing exception when retrieving not existing
TransactionProvider.
Should I write the above tests for TransactionService?
--
---
You received this message because you are subscribed to the Google Groups
"Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
---
You received this message because you are subscribed to the Google Groups
"Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
---
You received this message because you are subscribed to the Google Groups
"Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
---
You received this message because you are subscribed to the Google Groups
"Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
---
You received this message because you are subscribed to the Google Groups
"Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
---
You received this message because you are subscribed to the Google Groups
"Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.