Thanks again, in advance -
I'm pulling the never-ending thread discussed in the user's guide, and
I noticed yet another place where my code could be refactored.
I have an application that connects to both a sql server, and a db2
database - so there is a class that provides these connections
helper.getSqlServerConnection();
This helper is initialized by Guice and the connection parameters are
injected from a properties file with @Named.
The problem with this, is that my code is still coupled with the
Connection, so my tests either have to hit a test DB isntance, or the
real DB - neither of which I really want.
My question is, how do I inject this dependency on Connection? Keep
in mind, I need two different Connection's configured just a bit
differently.
Thanks!
I sometimes bind these scripted mocks in anonymous Guice modules in
the test, but if I'm just testing a single class I typically create it
by hand and pass the mock in avoiding Guice altogether.
import static org.easymock.EasyMock.*;
//...
Connection mock = createMock(Connection.class);
expect(mock.prepareStatement("...")).andReturn(...); //prepare mock script
replay(mock);
//now begins the test...
MyDao dao = new MyDaoImpl(mock);
//assert various things against my dao
//finally assert script was followed
verify(mock);
Dhanji.
Thanks, I appreciate it - I was thinking about that route, but
wasn't sure if there was simply a better way to inject a connection.
On Nov 2, 11:20 am, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> I would suggest using a mocking framework like EasyMock for that. If
> you're unit testing, then you're probably only interested in a
> particular class's (or set of classes) functionality. If it requires a
> db connection you can provide it with an EasyMock control and write a
> "script" for how it is expected to play with the database.
>
> I sometimes bind these scripted mocks in anonymous Guice modules in
> the test, but if I'm just testing a single class I typically create it
> by hand and pass the mock in avoiding Guice altogether.
>
> import static org.easymock.EasyMock.*;
> //...
>
> Connection mock = createMock(Connection.class);
>
> expect(mock.prepareStatement("...")).andReturn(...); //prepare mock script
> replay(mock);
>
> //now begins the test...
> MyDao dao = new MyDaoImpl(mock);
>
> //assert various things against my dao
>
> //finally assert script was followed
> verify(mock);
>
> Dhanji.
>
> On 11/2/07, Adam Schaible <adam.schai...@gmail.com> wrote:
>
>
>
>
>
> > Hello everyone,
>
> > Thanks again, in advance -
>
> > I'm pulling the never-ending thread discussed in the user's guide, and
> > I noticed yet another place where my code could be refactored.
>
> > I have an application that connects to both a sql server, and a db2
> > database - so there is a class that provides these connections
>
> > helper.getSqlServerConnection();
>
> > This helper is initialized by Guice and the connection parameters are
> > injected from a properties file with @Named.
>
> > The problem with this, is that my code is still coupled with the
> > Connection, so my tests either have to hit a test DB isntance, or the
> > real DB - neither of which I really want.
>
> > My question is, how do I inject this dependency on Connection? Keep
> > in mind, I need two different Connection's configured just a bit
> > differently.
>
> > Thanks!- Hide quoted text -
>
> - Show quoted text -
I haven't tried it, but you might also want to consider Mayfly, which
is an in-memory database specifically for testing:
http://mayfly.sourceforge.net/
But then, that doesn't answer your question, because you still have to
inject whatever kind of connection you choose. You might want to try
something like this:
@Inject
Foo(@FirstDbKind Provider<Connection> firstConnectionProvider,
@SecondDbKind Provider<Connection> secondConnectionProvider) {
...
}
Or alternately, inject two instances of javax.sql.DataSource.
- Brian
On 11/2/07, Adam Schaible <adam.s...@gmail.com> wrote:
>
I agree with you in principle, mocked-integration tests are important.
However how do you account for the fact that SQL dialect and behavior
varies between vendors? I use hypersonic (another in-memory db that
ships with Hibernate) to do some basic integration-style tests.
But I know they don't give me any sort of real confidence that the
same code will work against another vendor. I think in these cases a
"proper" stack integration test is warranted for each implementation
stream (db2, sqlserver..).
OTOH testing that the client code is issuing the correct calls to
abstraction API is as simple as a unit test with mocked services.
Dhanji.
aka warp-persist ;)
Dhanji.
> The better way to do this would be to have persistence completely separate
> from the business rules. At that point, there is little confidence to be
> gained in testing the persistence layer with unit tests. Our goal is to get
> to a point where all business logic has been removed from the DAO layer
> (after getting things under test), and then replacing all DAO unit tests
> with integration level tests that talk to a real, live test database.
You still need unit tests that show that whatever persistence layer
you choose works with the flavor of database software you're using.
In practice, maybe you're using a persistence layer such as Hibernate,
and it has some unit tests for each database it supports, so you don't
have to write them yourself. But they're still there. It might be a
good idea to run Hibernate's unit tests to make sure that there are no
bugs caused by using a slightly different database configuration than
the Hibernate developers, and even to review their unit tests to see
whether they cover the use cases you're interested in.
- Brian