Unit Testing Tips and Tricks: Database Interaction - PowerPoint PPT Presentation

1 / 29
About This Presentation
Title:

Unit Testing Tips and Tricks: Database Interaction

Description:

create a mock that extends the object and overrides all its methods (works sometimes) ... { recordActivity('sI(' nUpdateIntervalMilliseconds ')'); public void ... – PowerPoint PPT presentation

Number of Views:40
Avg rating:3.0/5.0
Slides: 30
Provided by: louisk9
Category:

less

Transcript and Presenter's Notes

Title: Unit Testing Tips and Tricks: Database Interaction


1
Unit Testing Tips and Tricks Database
Interaction
  • Louis Thomas

2
Overview
  • Preaching about TDD
  • What is a Unit Test
  • Common Unit Testing Patterns
  • Unit Testing Database Interactions
  • Acceptance Tests With Databases

3
Are you test infected?
  • There are two kinds of people
  • People who dont like it
  • Cant be done attitude
  • People who do like it
  • I think I can attitude

4
Test Driven Development Is Hard
  • Conceptually, its simple!
  • (Sure, just like OO is simple)
  • Its a learning process. It will be hard at
    first.
  • Be creative!

5
Im Guilty
  • I'm guilty. I am a hack. I am an "impurist". I
    often don't do "pure" TDD.
  • I find TDD easier to do for some tasks than
    others. I do whatever I feel like. However, I
    like what I get with TDD, so I lean towards it
  • Unit tests are good even if you dont do TDD!

6
There Are Many Kinds Of Tests
  • Acceptance tests, user test, integration tests,
    unit tests black box, white box
  • All tests have merit if they can detect bugs.
  • Tests only have value if they are run!

7
Unit Tests
  • From developer's point of view.
  • Tests the smallest amount of a system that is
    interesting.
  • Often just one part of one class!
  • Highly automated

8
Unit Test Rule Of Thumb
  • If you are having trouble writing a unit test
  • or (for those of you who aren't test infected)if
    it's "impossible" to write a test for your
    system,
  • You are trying to test to much. Test a smaller
    chunk.

9
But How?
  • Sometimes objects have complex behaviors,
    extensive state, and tight relationships. This
    makes tests difficultset up is difficult and
    time consuming, and objects cannot be isolated.
  • (But wait, thats not right! Right?)

10
Loosening The Coupling
  • Introduce interfaces between complex objects.
  • Create a mock object to stand in for the complex
    object.
  • Repeat as needed. (Be creative.)

11
Creating Interfaces
  • If it's our object, just create an interface!
  • if it's not our object,
  • create a mock that extends the object and
    overrides all its methods (works sometimes)
  • create an interface anyway and create an adapter
    for the foreign object
  • Example WallClock

12
Example WallClock
Interface
public interface WallClock long getTime()
Wrapper for normal system service
public class DefaultWallClock implements
WallClock public static final WallClock
INSTANCEnew DefaultWallClock() public long
getTime() return System.currentTimeMilli
s()
13
Mock Objects
  • Start out as simple as possible (throw exceptions
    on all methods).
  • Add recording of incoming method calls
  • - ex RecordingMockObject, Thumbprinters

14
Example ReportingMockObject
public class ReportingMockObject
StringBuffer m_stringBuffernew StringBuffer()
//---------------------------------------------
------------------- public String
getActivityRecordAndReset() String
sActivityRecordm_stringBuffer.toString()
m_stringBuffernew StringBuffer()
return sActivityRecord
//------------------------------------------------
---------------- public void
recordActivity(String sMessage)
m_stringBuffer.append(sMessage)
15
Example MockClientSession
public class MockClientSession extends
ReportingMockObject implements ClientSession
public MockClientSession() public
void flushOutgoingBuffer()
recordActivity("fOB") public void
setInterval(int nUpdateIntervalMilliseconds)
recordActivity("sI("nUpdateIntervalMilliseco
nds")") public void
notifyNewOutgoingData()
recordActivity("nNOD") public String
getClientName() recordActivity("gCN")
return "mockClient" //
16
Example MockMultiTableSessionListener
public class MockMultiTableSessionListener
extends ReportingMockObject implements
MultiTableSession.Listener public
interface Thumbprinter String
getThumbprint(MultiTableSession.Update update)
String getThumbprint(SessionState
sessionState) //

private final Thumbprinter m_thumbprinter
// public MockMultiTableSessionListener(Thumb
printer thumbprinter)
m_thumbprinterthumbprinter //
public void sessionStateNotification(SessionState
sessionState) if (truem_bLogSessionSta
teNotification) recordActivity("sSN(
"m_thumbprinter.getThumbprint(sessionState)")")

17
Mock Objects, contd
  • Add facility for sending back canned responses
  • (ex, setNextReply, setFailOnNextRequest)

18
Example WallClock
public class MockWallClock implements WallClock
private long m_nextTimes private
int m_nNextTimeIndex public void
setNextTime(long nNextTime)
setNextTimeList(new long nNextTime)
public void setNextTimeList(long nextTimes)
Require.neqNull(nextTimes,
"nextTimes") m_nextTimesnextTimes
m_nNextTimeIndex0 public long
getTime() Assert.neqNull(m_nextTimes,
"m_nextTimes") long nNextTimem_nextTimes
m_nNextTimeIndex m_nNextTimeIndex
if (m_nextTimes.lengthm_nNextTimeIndex)
m_nextTimesnull
return nNextTime
19
Mock Objects, contd
  • Do whatever you need
  • Often one mock object will support all tests for
    a given object, but can create special ones for
    certain tests
  • Often, one mock object will support tests for
    many objects that interact with it

20
Mock Object Frameworks
  • EasyMock (http//easymock.org)
  • jMock (http//www.jmock.org/)
  • YMMV!

21
Object Mother (?)
  • Sometimes you will need a complex data structure
    set up. Refactor mercilessly.
  • Especially if you need canned data that is
    ancillary to the test, it is often worth while to
    factor creation out into a static method in a
    util class so you can use it as necessary
    thereafter.

22
Testing Accessor
  • Problem there are private methods you would like
    to test, or private members you would like to
    inspect for your test
  • You could make them public, but they really are
    private
  • Alternative an inner class! TestingAccessor

23
Example TestingAccessor
//
// testing private
WallClock m_wallClockDefaultWallClock.instance
private IStepper m_getConStepperDefaultStepper
.instance private IStepper
m_maintStepperDefaultStepper.instance
public class TestingAccessor public
void setWallClock(WallClock wallClock)
m_wallClockwallClock public void
setGetConStepper(IStepper stepper)
m_getConStepperstepper public void
setMaintStepper(IStepper stepper)
m_maintStepperstepper public void
setNextOverdueConnectionCheck(long
tsNextOverdueConnectionCheck)
m_tsNextOverdueConnectionChecktsNextOverdueConne
ctionCheck public int
getAllConnectionsSize() return
m_allConnections.size() public int
getUnusedConnectionsSize() return
m_unusedConnections.size() public int
getTotalConnections() return m_nTotalConnections
public void cacheMaintenaceThread()
DBConnectionPool.this.cacheMaintenaceThread()
public void doNotifyAll() synchronized
(m_oStateLock) m_oStateLock.notifyAll()
public TestingAccessor getTestingAccessor()
return new TestingAccessor()
24
Testing Database Interactions
  • You should be thankful! All the database classes
    are interfaces already!
  • Create mocks and away you go
  • Insert / update / delete easy

25
Testing Database Interactions, Contd
  • Read trickier
  • Can use hard coded expectations
  • Mocks will act as factories statements return
    record sets
  • load your mock statement with the mock
    record set to return.
  • load your mock connection with the mock
    statement to return.
  • Can start out with mocks with hard coded returns,
    but will probably refactor into more general
    objects.
  • Ex Simulated Database Framework

26
Acceptance Tests With Databases
  • An acceptance test Want to test the "whole" app.
  • Good for testing that the database really likes
    the SQL we hardcoded in the unit tests, and
    really responds the way we expect

27
Acceptance Tests With Databases, Contd
  • Big question is, how can we automate? I built up
    a toolkit as I went.
  • BulkLoadData reads CSV files and loads data into
    DB (use Excel to edit)
  • ExecuteSqlScript processes a text file of SQL
    commands.
  • Used to create tables, etc.
  • ExecuteDatabaseSetupScript allows me to write
    little scripts
  • Knows about 4 commands, including BulkLoadData
    and ExecuteSqlScript
  • TestResource framework

28
Acceptance Tests With Databases, Contd
  • Big question is, how can we automate? I built up
    a toolkit as I went.
  • TestResource framework
  • I can define test resources my test needs,
    setup/teardown methods, and dependencies.
  • Resources will set themselves up from any initial
    state (ex, delete all rows in table and reload)
  • Now, the acceptance test can just declare all the
    resources it needs, and framework will set them
    up. Just needs to mark which resources it
    dirties, so they can be reset for subsequent
    tests.

29
Summary
  • Preaching about TDD
  • What is a Unit Test
  • Common Unit Testing Patterns
  • Unit Testing Database Interactions
  • Acceptance Tests With Databases
  • Questions / demos!
Write a Comment
User Comments (0)
About PowerShow.com