Unit testing - Mock objects for SqlSession and SqlSession factory

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Unit testing - Mock objects for SqlSession and SqlSession factory

Nicolai Willems
Hello MyBatis users

Recently I began developing with MyBatis for a common database layer
for our java apps at work

Yesterday I started doing some unit testing and found no way of doing
this nice and easy.
So I developed some Mock objects for SqlSessionFactory and SqlSession.
As for now I've
implemented openSession() and variations hereof in SqlSessionFactory
in MockSqlSession,
they all just return a MockSqlSession object. In the MockSqlSession
I've implemented getMapper(),
it uses reflection and have some simple rules:
1. You need to make MockMapperImplementations which implements the
actual interface.
2. The MockMapper need to be named Mock<MapperFileClass>, unless it
has an I(capital)
     as character in name(I guess some of them have) it won't get in
there,
     example ISwitchDbMapper has MockSwitchDbMapper.
3. It needs to be in the same package as your mapper-interface(This is
easily overcome by making the package in your test dir)

So for example if you have a DAO which receives a SqlSessionFactory
as parameter in the constructor,
then instead of passing in a real SqlSessionFactory you give it a
MockSqlSessionFactory, this reduces the overhead
when accessing a real database(or in my case two).
For example in your test:
@Override
protected void setUp() throws Exception {
    super.setUp();
    SqlSessionFactory fact = new MockSqlSessionFactory();
    this.dao = new SwitchDbDao(fact);
}

I would be happy to commit these classes or I could just submit them
somewhere online accessible to all.
If you have any contributions for my implementation, please add them -
for now in email form.
I can mail them to you or you can take a look in a little while at my
blog(http://chillems.blogspot.com) where I'm going to
post both classes.

That should be all
Regards
Nicolai Willems
Software Developer @ Zylinc.com
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing - Mock objects for SqlSession and SqlSession factory

Larry Meadors
I have been using mockito to mock these. It's the bomb.

Larry


On Fri, Sep 24, 2010 at 2:31 PM, Nicolai Willems <[hidden email]> wrote:

> Hello MyBatis users
>
> Recently I began developing with MyBatis for a common database layer
> for our java apps at work
>
> Yesterday I started doing some unit testing and found no way of doing
> this nice and easy.
> So I developed some Mock objects for SqlSessionFactory and SqlSession.
> As for now I've
> implemented openSession() and variations hereof in SqlSessionFactory
> in MockSqlSession,
> they all just return a MockSqlSession object. In the MockSqlSession
> I've implemented getMapper(),
> it uses reflection and have some simple rules:
> 1. You need to make MockMapperImplementations which implements the
> actual interface.
> 2. The MockMapper need to be named Mock<MapperFileClass>, unless it
> has an I(capital)
>     as character in name(I guess some of them have) it won't get in
> there,
>     example ISwitchDbMapper has MockSwitchDbMapper.
> 3. It needs to be in the same package as your mapper-interface(This is
> easily overcome by making the package in your test dir)
>
> So for example if you have a DAO which receives a SqlSessionFactory
> as parameter in the constructor,
> then instead of passing in a real SqlSessionFactory you give it a
> MockSqlSessionFactory, this reduces the overhead
> when accessing a real database(or in my case two).
> For example in your test:
> @Override
> protected void setUp() throws Exception {
>    super.setUp();
>    SqlSessionFactory fact = new MockSqlSessionFactory();
>    this.dao = new SwitchDbDao(fact);
> }
>
> I would be happy to commit these classes or I could just submit them
> somewhere online accessible to all.
> If you have any contributions for my implementation, please add them -
> for now in email form.
> I can mail them to you or you can take a look in a little while at my
> blog(http://chillems.blogspot.com) where I'm going to
> post both classes.
>
> That should be all
> Regards
> Nicolai Willems
> Software Developer @ Zylinc.com
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing - Mock objects for SqlSession and SqlSession factory

Nicolai Willems


On Fri, Sep 24, 2010 at 10:42 PM, Larry Meadors <[hidden email]> wrote:
I have been using mockito to mock these. It's the bomb.

Mockito looks very nice. How would you do in the case described below?
And what are you testing when using mockito?(not asking for a how-to, 
maybee just a stub of test-code)

/Nicolai
 
Larry


On Fri, Sep 24, 2010 at 2:31 PM, Nicolai Willems <[hidden email]> wrote:
> Hello MyBatis users
>
> Recently I began developing with MyBatis for a common database layer
> for our java apps at work
>
> Yesterday I started doing some unit testing and found no way of doing
> this nice and easy.
> So I developed some Mock objects for SqlSessionFactory and SqlSession.
> As for now I've
> implemented openSession() and variations hereof in SqlSessionFactory
> in MockSqlSession,
> they all just return a MockSqlSession object. In the MockSqlSession
> I've implemented getMapper(),
> it uses reflection and have some simple rules:
> 1. You need to make MockMapperImplementations which implements the
> actual interface.
> 2. The MockMapper need to be named Mock<MapperFileClass>, unless it
> has an I(capital)
>     as character in name(I guess some of them have) it won't get in
> there,
>     example ISwitchDbMapper has MockSwitchDbMapper.
> 3. It needs to be in the same package as your mapper-interface(This is
> easily overcome by making the package in your test dir)
>
> So for example if you have a DAO which receives a SqlSessionFactory
> as parameter in the constructor,
> then instead of passing in a real SqlSessionFactory you give it a
> MockSqlSessionFactory, this reduces the overhead
> when accessing a real database(or in my case two).
> For example in your test:
> @Override
> protected void setUp() throws Exception {
>    super.setUp();
>    SqlSessionFactory fact = new MockSqlSessionFactory();
>    this.dao = new SwitchDbDao(fact);
> }
>
> I would be happy to commit these classes or I could just submit them
> somewhere online accessible to all.
> If you have any contributions for my implementation, please add them -
> for now in email form.
> I can mail them to you or you can take a look in a little while at my
> blog(http://chillems.blogspot.com) where I'm going to
> post both classes.
>
> That should be all
> Regards
> Nicolai Willems
> Software Developer @ Zylinc.com

Reply | Threaded
Open this post in threaded view
|

Re: Unit testing - Mock objects for SqlSession and SqlSession factory

Larry Meadors
I use mockito to mock the database interaction so I can test my other classes.

Here's the pidgin code (gmail sucks as an IDE):

SqlSessionFactory ssf = mock(SqlSessionFactory.class);
SqlSession ss = mock(SqlSession.class);
SomeMapper some = mock(SomeMapper.class);

when(ssf.openSession()).thenReturn(ss));
when(ss.getMapper(SomeMapper.class)).thenReturn(some);

You could probably put together a Answer class to reply to getMapper()
with a mocked mapper, but for the most part, it'd be useless because
you need to provide the mocked behavior.

Larry


On Fri, Sep 24, 2010 at 3:00 PM, Nicolai Willems <[hidden email]> wrote:

>
>
> On Fri, Sep 24, 2010 at 10:42 PM, Larry Meadors <[hidden email]>
> wrote:
>>
>> I have been using mockito to mock these. It's the bomb.
>
> Mockito looks very nice. How would you do in the case described below?
> And what are you testing when using mockito?(not asking for a how-to,
> maybee just a stub of test-code)
> /Nicolai
>
>>
>> Larry
>>
>>
>> On Fri, Sep 24, 2010 at 2:31 PM, Nicolai Willems <[hidden email]>
>> wrote:
>> > Hello MyBatis users
>> >
>> > Recently I began developing with MyBatis for a common database layer
>> > for our java apps at work
>> >
>> > Yesterday I started doing some unit testing and found no way of doing
>> > this nice and easy.
>> > So I developed some Mock objects for SqlSessionFactory and SqlSession.
>> > As for now I've
>> > implemented openSession() and variations hereof in SqlSessionFactory
>> > in MockSqlSession,
>> > they all just return a MockSqlSession object. In the MockSqlSession
>> > I've implemented getMapper(),
>> > it uses reflection and have some simple rules:
>> > 1. You need to make MockMapperImplementations which implements the
>> > actual interface.
>> > 2. The MockMapper need to be named Mock<MapperFileClass>, unless it
>> > has an I(capital)
>> >     as character in name(I guess some of them have) it won't get in
>> > there,
>> >     example ISwitchDbMapper has MockSwitchDbMapper.
>> > 3. It needs to be in the same package as your mapper-interface(This is
>> > easily overcome by making the package in your test dir)
>> >
>> > So for example if you have a DAO which receives a SqlSessionFactory
>> > as parameter in the constructor,
>> > then instead of passing in a real SqlSessionFactory you give it a
>> > MockSqlSessionFactory, this reduces the overhead
>> > when accessing a real database(or in my case two).
>> > For example in your test:
>> > @Override
>> > protected void setUp() throws Exception {
>> >    super.setUp();
>> >    SqlSessionFactory fact = new MockSqlSessionFactory();
>> >    this.dao = new SwitchDbDao(fact);
>> > }
>> >
>> > I would be happy to commit these classes or I could just submit them
>> > somewhere online accessible to all.
>> > If you have any contributions for my implementation, please add them -
>> > for now in email form.
>> > I can mail them to you or you can take a look in a little while at my
>> > blog(http://chillems.blogspot.com) where I'm going to
>> > post both classes.
>> >
>> > That should be all
>> > Regards
>> > Nicolai Willems
>> > Software Developer @ Zylinc.com
>
>
Tim
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing - Mock objects for SqlSession and SqlSession factory

Tim
That's awesome stuff Larry but bomb's are not cool.
Remember when Mac's errored out with the bomb guy?
No one thought he was cool.

And now you know. And knowing is half the battle.

On Fri, Sep 24, 2010 at 4:10 PM, Larry Meadors <[hidden email]> wrote:

> I use mockito to mock the database interaction so I can test my other classes.
>
> Here's the pidgin code (gmail sucks as an IDE):
>
> SqlSessionFactory ssf = mock(SqlSessionFactory.class);
> SqlSession ss = mock(SqlSession.class);
> SomeMapper some = mock(SomeMapper.class);
>
> when(ssf.openSession()).thenReturn(ss));
> when(ss.getMapper(SomeMapper.class)).thenReturn(some);
>
> You could probably put together a Answer class to reply to getMapper()
> with a mocked mapper, but for the most part, it'd be useless because
> you need to provide the mocked behavior.
>
> Larry
>
>
> On Fri, Sep 24, 2010 at 3:00 PM, Nicolai Willems <[hidden email]> wrote:
>>
>>
>> On Fri, Sep 24, 2010 at 10:42 PM, Larry Meadors <[hidden email]>
>> wrote:
>>>
>>> I have been using mockito to mock these. It's the bomb.
>>
>> Mockito looks very nice. How would you do in the case described below?
>> And what are you testing when using mockito?(not asking for a how-to,
>> maybee just a stub of test-code)
>> /Nicolai
>>
>>>
>>> Larry
>>>
>>>
>>> On Fri, Sep 24, 2010 at 2:31 PM, Nicolai Willems <[hidden email]>
>>> wrote:
>>> > Hello MyBatis users
>>> >
>>> > Recently I began developing with MyBatis for a common database layer
>>> > for our java apps at work
>>> >
>>> > Yesterday I started doing some unit testing and found no way of doing
>>> > this nice and easy.
>>> > So I developed some Mock objects for SqlSessionFactory and SqlSession.
>>> > As for now I've
>>> > implemented openSession() and variations hereof in SqlSessionFactory
>>> > in MockSqlSession,
>>> > they all just return a MockSqlSession object. In the MockSqlSession
>>> > I've implemented getMapper(),
>>> > it uses reflection and have some simple rules:
>>> > 1. You need to make MockMapperImplementations which implements the
>>> > actual interface.
>>> > 2. The MockMapper need to be named Mock<MapperFileClass>, unless it
>>> > has an I(capital)
>>> >     as character in name(I guess some of them have) it won't get in
>>> > there,
>>> >     example ISwitchDbMapper has MockSwitchDbMapper.
>>> > 3. It needs to be in the same package as your mapper-interface(This is
>>> > easily overcome by making the package in your test dir)
>>> >
>>> > So for example if you have a DAO which receives a SqlSessionFactory
>>> > as parameter in the constructor,
>>> > then instead of passing in a real SqlSessionFactory you give it a
>>> > MockSqlSessionFactory, this reduces the overhead
>>> > when accessing a real database(or in my case two).
>>> > For example in your test:
>>> > @Override
>>> > protected void setUp() throws Exception {
>>> >    super.setUp();
>>> >    SqlSessionFactory fact = new MockSqlSessionFactory();
>>> >    this.dao = new SwitchDbDao(fact);
>>> > }
>>> >
>>> > I would be happy to commit these classes or I could just submit them
>>> > somewhere online accessible to all.
>>> > If you have any contributions for my implementation, please add them -
>>> > for now in email form.
>>> > I can mail them to you or you can take a look in a little while at my
>>> > blog(http://chillems.blogspot.com) where I'm going to
>>> > post both classes.
>>> >
>>> > That should be all
>>> > Regards
>>> > Nicolai Willems
>>> > Software Developer @ Zylinc.com
>>
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing - Mock objects for SqlSession and SqlSession factory

Larry Meadors
It's Friday. Who let Tim out of his cage? :)

On Fri, Sep 24, 2010 at 3:38 PM, Tim <[hidden email]> wrote:

> That's awesome stuff Larry but bomb's are not cool.
> Remember when Mac's errored out with the bomb guy?
> No one thought he was cool.
>
> And now you know. And knowing is half the battle.
>
> On Fri, Sep 24, 2010 at 4:10 PM, Larry Meadors <[hidden email]> wrote:
>> I use mockito to mock the database interaction so I can test my other classes.
>>
>> Here's the pidgin code (gmail sucks as an IDE):
>>
>> SqlSessionFactory ssf = mock(SqlSessionFactory.class);
>> SqlSession ss = mock(SqlSession.class);
>> SomeMapper some = mock(SomeMapper.class);
>>
>> when(ssf.openSession()).thenReturn(ss));
>> when(ss.getMapper(SomeMapper.class)).thenReturn(some);
>>
>> You could probably put together a Answer class to reply to getMapper()
>> with a mocked mapper, but for the most part, it'd be useless because
>> you need to provide the mocked behavior.
>>
>> Larry
>>
>>
>> On Fri, Sep 24, 2010 at 3:00 PM, Nicolai Willems <[hidden email]> wrote:
>>>
>>>
>>> On Fri, Sep 24, 2010 at 10:42 PM, Larry Meadors <[hidden email]>
>>> wrote:
>>>>
>>>> I have been using mockito to mock these. It's the bomb.
>>>
>>> Mockito looks very nice. How would you do in the case described below?
>>> And what are you testing when using mockito?(not asking for a how-to,
>>> maybee just a stub of test-code)
>>> /Nicolai
>>>
>>>>
>>>> Larry
>>>>
>>>>
>>>> On Fri, Sep 24, 2010 at 2:31 PM, Nicolai Willems <[hidden email]>
>>>> wrote:
>>>> > Hello MyBatis users
>>>> >
>>>> > Recently I began developing with MyBatis for a common database layer
>>>> > for our java apps at work
>>>> >
>>>> > Yesterday I started doing some unit testing and found no way of doing
>>>> > this nice and easy.
>>>> > So I developed some Mock objects for SqlSessionFactory and SqlSession.
>>>> > As for now I've
>>>> > implemented openSession() and variations hereof in SqlSessionFactory
>>>> > in MockSqlSession,
>>>> > they all just return a MockSqlSession object. In the MockSqlSession
>>>> > I've implemented getMapper(),
>>>> > it uses reflection and have some simple rules:
>>>> > 1. You need to make MockMapperImplementations which implements the
>>>> > actual interface.
>>>> > 2. The MockMapper need to be named Mock<MapperFileClass>, unless it
>>>> > has an I(capital)
>>>> >     as character in name(I guess some of them have) it won't get in
>>>> > there,
>>>> >     example ISwitchDbMapper has MockSwitchDbMapper.
>>>> > 3. It needs to be in the same package as your mapper-interface(This is
>>>> > easily overcome by making the package in your test dir)
>>>> >
>>>> > So for example if you have a DAO which receives a SqlSessionFactory
>>>> > as parameter in the constructor,
>>>> > then instead of passing in a real SqlSessionFactory you give it a
>>>> > MockSqlSessionFactory, this reduces the overhead
>>>> > when accessing a real database(or in my case two).
>>>> > For example in your test:
>>>> > @Override
>>>> > protected void setUp() throws Exception {
>>>> >    super.setUp();
>>>> >    SqlSessionFactory fact = new MockSqlSessionFactory();
>>>> >    this.dao = new SwitchDbDao(fact);
>>>> > }
>>>> >
>>>> > I would be happy to commit these classes or I could just submit them
>>>> > somewhere online accessible to all.
>>>> > If you have any contributions for my implementation, please add them -
>>>> > for now in email form.
>>>> > I can mail them to you or you can take a look in a little while at my
>>>> > blog(http://chillems.blogspot.com) where I'm going to
>>>> > post both classes.
>>>> >
>>>> > That should be all
>>>> > Regards
>>>> > Nicolai Willems
>>>> > Software Developer @ Zylinc.com
>>>
>>>
>>
>
Tim
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing - Mock objects for SqlSession and SqlSession factory

Tim
My engrish is the bomb (see? bad connotation)
s/bomb's/bombs/

On Fri, Sep 24, 2010 at 4:40 PM, Larry Meadors <[hidden email]> wrote:

> It's Friday. Who let Tim out of his cage? :)
>
> On Fri, Sep 24, 2010 at 3:38 PM, Tim <[hidden email]> wrote:
>> That's awesome stuff Larry but bomb's are not cool.
>> Remember when Mac's errored out with the bomb guy?
>> No one thought he was cool.
>>
>> And now you know. And knowing is half the battle.
>>
>> On Fri, Sep 24, 2010 at 4:10 PM, Larry Meadors <[hidden email]> wrote:
>>> I use mockito to mock the database interaction so I can test my other classes.
>>>
>>> Here's the pidgin code (gmail sucks as an IDE):
>>>
>>> SqlSessionFactory ssf = mock(SqlSessionFactory.class);
>>> SqlSession ss = mock(SqlSession.class);
>>> SomeMapper some = mock(SomeMapper.class);
>>>
>>> when(ssf.openSession()).thenReturn(ss));
>>> when(ss.getMapper(SomeMapper.class)).thenReturn(some);
>>>
>>> You could probably put together a Answer class to reply to getMapper()
>>> with a mocked mapper, but for the most part, it'd be useless because
>>> you need to provide the mocked behavior.
>>>
>>> Larry
>>>
>>>
>>> On Fri, Sep 24, 2010 at 3:00 PM, Nicolai Willems <[hidden email]> wrote:
>>>>
>>>>
>>>> On Fri, Sep 24, 2010 at 10:42 PM, Larry Meadors <[hidden email]>
>>>> wrote:
>>>>>
>>>>> I have been using mockito to mock these. It's the bomb.
>>>>
>>>> Mockito looks very nice. How would you do in the case described below?
>>>> And what are you testing when using mockito?(not asking for a how-to,
>>>> maybee just a stub of test-code)
>>>> /Nicolai
>>>>
>>>>>
>>>>> Larry
>>>>>
>>>>>
>>>>> On Fri, Sep 24, 2010 at 2:31 PM, Nicolai Willems <[hidden email]>
>>>>> wrote:
>>>>> > Hello MyBatis users
>>>>> >
>>>>> > Recently I began developing with MyBatis for a common database layer
>>>>> > for our java apps at work
>>>>> >
>>>>> > Yesterday I started doing some unit testing and found no way of doing
>>>>> > this nice and easy.
>>>>> > So I developed some Mock objects for SqlSessionFactory and SqlSession.
>>>>> > As for now I've
>>>>> > implemented openSession() and variations hereof in SqlSessionFactory
>>>>> > in MockSqlSession,
>>>>> > they all just return a MockSqlSession object. In the MockSqlSession
>>>>> > I've implemented getMapper(),
>>>>> > it uses reflection and have some simple rules:
>>>>> > 1. You need to make MockMapperImplementations which implements the
>>>>> > actual interface.
>>>>> > 2. The MockMapper need to be named Mock<MapperFileClass>, unless it
>>>>> > has an I(capital)
>>>>> >     as character in name(I guess some of them have) it won't get in
>>>>> > there,
>>>>> >     example ISwitchDbMapper has MockSwitchDbMapper.
>>>>> > 3. It needs to be in the same package as your mapper-interface(This is
>>>>> > easily overcome by making the package in your test dir)
>>>>> >
>>>>> > So for example if you have a DAO which receives a SqlSessionFactory
>>>>> > as parameter in the constructor,
>>>>> > then instead of passing in a real SqlSessionFactory you give it a
>>>>> > MockSqlSessionFactory, this reduces the overhead
>>>>> > when accessing a real database(or in my case two).
>>>>> > For example in your test:
>>>>> > @Override
>>>>> > protected void setUp() throws Exception {
>>>>> >    super.setUp();
>>>>> >    SqlSessionFactory fact = new MockSqlSessionFactory();
>>>>> >    this.dao = new SwitchDbDao(fact);
>>>>> > }
>>>>> >
>>>>> > I would be happy to commit these classes or I could just submit them
>>>>> > somewhere online accessible to all.
>>>>> > If you have any contributions for my implementation, please add them -
>>>>> > for now in email form.
>>>>> > I can mail them to you or you can take a look in a little while at my
>>>>> > blog(http://chillems.blogspot.com) where I'm going to
>>>>> > post both classes.
>>>>> >
>>>>> > That should be all
>>>>> > Regards
>>>>> > Nicolai Willems
>>>>> > Software Developer @ Zylinc.com
>>>>
>>>>
>>>
>>
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing - Mock objects for SqlSession and SqlSession factory

Clinton Begin
Administrator
In reply to this post by Nicolai Willems
Sorry for not reading the whole post... kind of in a rush... I'll get out two points, do with them what you will:

* I don't mock them.  I have layered testing, so my mappers hit the database in a suite of tests specifically designed to test the *SQL*... this is an important part of unit testing.  Whoever said don't hit the database when testing was smoking something.  :-)  Perhaps don't do it without care, but SQL must be part of your testing scope, or your app isn't covered.

*  As for isolation of layers above the Data Access Layer, I tend to use mappers, which are easily "mockable" because they are just pojos really...  Mixed with a good DI framework like Guice, most of my application doesn't even know what MyBatis is...

But when you do need to, Larry's advice for Mockito is great.

Clinton

On Fri, Sep 24, 2010 at 2:31 PM, Nicolai Willems <[hidden email]> wrote:
Hello MyBatis users

Recently I began developing with MyBatis for a common database layer
for our java apps at work

Yesterday I started doing some unit testing and found no way of doing
this nice and easy.
So I developed some Mock objects for SqlSessionFactory and SqlSession.
As for now I've
implemented openSession() and variations hereof in SqlSessionFactory
in MockSqlSession,
they all just return a MockSqlSession object. In the MockSqlSession
I've implemented getMapper(),
it uses reflection and have some simple rules:
1. You need to make MockMapperImplementations which implements the
actual interface.
2. The MockMapper need to be named Mock<MapperFileClass>, unless it
has an I(capital)
    as character in name(I guess some of them have) it won't get in
there,
    example ISwitchDbMapper has MockSwitchDbMapper.
3. It needs to be in the same package as your mapper-interface(This is
easily overcome by making the package in your test dir)

So for example if you have a DAO which receives a SqlSessionFactory
as parameter in the constructor,
then instead of passing in a real SqlSessionFactory you give it a
MockSqlSessionFactory, this reduces the overhead
when accessing a real database(or in my case two).
For example in your test:
@Override
protected void setUp() throws Exception {
   super.setUp();
   SqlSessionFactory fact = new MockSqlSessionFactory();
   this.dao = new SwitchDbDao(fact);
}

I would be happy to commit these classes or I could just submit them
somewhere online accessible to all.
If you have any contributions for my implementation, please add them -
for now in email form.
I can mail them to you or you can take a look in a little while at my
blog(http://chillems.blogspot.com) where I'm going to
post both classes.

That should be all
Regards
Nicolai Willems
Software Developer @ Zylinc.com