Hello,

I am wondering if our approach to testing our DAOs and Service Methods is a 
sound approach, or if there are better ways of setting up tests?  I've read 
http://blog.jooq.org/2014/06/26/stop-unit-testing-database-code/, and 
understand the main points there, as well as reviewed prior forum posts on 
the topic.

The example below deals with a very simple DAO, but it serves as a good 
case study.  Thank you in advance for any input!

*Our Class*
We've written a simple class that will CRUD "emailTemplates" from our 
database.  You can think of "Mnemonic" as just a unique identifier.  This 
allows us to get fancy autocomplete in our IDE when requesting a particular 
email template.  Anyway, here's the interface:

public interface EmailTemplateDao {
    EmailTemplate findByMnemonic(EmailTemplateMnemonic emailTemplateMnemonic
);

    void setEmailTemplate( EmailTemplate emailTemplate );

    EmailTemplate insert();

    EmailTemplate update();

    void delete( EmailTemplateMnemonic emailTemplateMnemonic );
}

All these methods are implemented using standard jOOQ tools: the DSLContext 
and UpdatableRecord.  Our testing approach is basically:

   - Mock any dependencies this class has
   - Connect to the real database (both locally and our testDb on Jenkins)
   - Do our database operations in the test (e.g. Insert)
   - Delete the item just tested

Again, nothing fancy.  I've pasted our file below.  My questions are:

   1. We are directly inserting data, and then deleting our data as part of 
   our test. We strategically chose to insert TEST_EMAIL_TEMPLATE to avoid 
   conflicting with other prepopulated data in our test environment.  Is the 
   "do something in the database, and then clean up after yourself" paradigm 
   pretty standard?  Logically, I can't imagine any other way to do this.
   2. Are there are any issues with scaling this approach?  For example, 
   when we have hundreds of tests, will we want to be doing something 
   different here.
   3. Can I safely assume that a test like this MUST be run sequentially 
   and can never be run in parallel?  Do you address that slowness by just 
   setting up a nightly test run?
   4. Any other points or links to good resources for testing DAOs and 
   Service Methods?  Or top books on the topic?

Thank you again for your input!

Josh

public class EmailTemplateDaoTest {

    private Http.Request requestMock = mock(Http.Request.class);
    private OrgContext orgContextMock = mock(OrgContext.class);

    private AragornDatabaseConnection aragornDatabaseConnection;
    private EmailTemplateDao emailTemplateDao;

    @Before
    public void setup() {
        // Define an HTTP.context since our Database Connection is passed 
around via the ctx() object
        Http.Context.current.set( new Http.Context( 1L, null, requestMock, 
new HashMap<String, String>(), new HashMap<String, String>(), new HashMap<
String, Object>() ) );

        // Default to OrgId #1
        when( orgContextMock.getOrgIdFromRequestHostname() ).thenReturn( 1 
);

        // Directly instantiate other dependencies
        aragornDatabaseConnection = new AragornDatabaseConnectionImpl( 
orgContextMock );
        emailTemplateDao = new EmailTemplateDaoImpl( 
aragornDatabaseConnection );
    }

    @Test
    public void testInsert() {
        running( fakeApplication(), () -> {

            aragornDatabaseConnection.setConnection( DB.getConnection( "mydb
" ) );

            EmailTemplate emailTemplate = new EmailTemplate();
            emailTemplate.setEmailTemplateMnemonic( EmailTemplateMnemonic.
TEST_EMAIL_TEMPLATE.getValue() );
            emailTemplate.setFromEmail( "[email protected]" );
            emailTemplate.setFromName( "Josh Padnick" );
            emailTemplate.setMessageBody( "Hello, this is an email!" );
            emailTemplate.setMessageSubject( "Testing!" );
            emailTemplate.setMetaDescription( "Description here" );
            emailTemplate.setMetaTitle( "Test Email" );
            emailTemplateDao.setEmailTemplate( emailTemplate );

            EmailTemplate emailTemplateInserted = new EmailTemplate();

            try {
                emailTemplateInserted = emailTemplateDao.insert();
            } catch (SQLException e) {
                Assert.fail();
            }

            assertThat( emailTemplateInserted.getEmailTemplateId() ).
isNotEqualTo( emailTemplate.getEmailTemplateId() );
            assertThat( emailTemplateInserted.getEmailTemplateMnemonic() ).
isEqualTo( emailTemplate.getEmailTemplateMnemonic() );
            assertThat( emailTemplateInserted.getMessageBody() ).isEqualTo( 
emailTemplate.getMessageBody() );
        });
    }


    @Test
    // Aragorn should not permit the same template to be inserted twice 
because each mnemonic must be unique
    public void testDuplicateInsertThrowsException() {
        running( fakeApplication(), () -> {

            aragornDatabaseConnection.setConnection( DB.getConnection( "mydb
" ) );

            // Insert the first template (should succeed)
            EmailTemplate emailTemplate = new EmailTemplate();
            emailTemplate.setEmailTemplateMnemonic( EmailTemplateMnemonic.
TEST_EMAIL_TEMPLATE.getValue() );
            emailTemplate.setFromEmail( "[email protected]" );
            emailTemplate.setFromName( "Josh Padnick" );
            emailTemplate.setMessageBody( "Hello, this is an email!" );
            emailTemplate.setMessageSubject( "Testing!" );
            emailTemplate.setMetaDescription( "Description here" );
            emailTemplate.setMetaTitle( "Test Email" );
            emailTemplateDao.setEmailTemplate( emailTemplate );

            try {
                emailTemplateDao.insert();
            } catch (SQLException e) {
                Assert.fail("Failed to insert first EmailTemplate");
            }

            // Now insert the second, duplicate template (should fail)
            EmailTemplate emailTemplateDupe = new EmailTemplate();
            emailTemplateDupe.setEmailTemplateMnemonic( 
EmailTemplateMnemonic.TEST_EMAIL_TEMPLATE.getValue() );
            emailTemplateDupe.setFromEmail( "[email protected]" );
            emailTemplateDupe.setFromName( "Joshua Padnick" );
            emailTemplateDupe.setMessageBody( "Hello, this is an email." );
            emailTemplateDupe.setMessageSubject( "Testing..." );
            emailTemplateDupe.setMetaDescription( "Description here!" );
            emailTemplateDupe.setMetaTitle( "Test Email of Amazement" );
            emailTemplateDao.setEmailTemplate( emailTemplateDupe );

            try {
                emailTemplateDao.insert();
            } catch (SQLException | org.jooq.exception.DataAccessException e
) {
                // We don't permit the same mnemonic to be entered twice
                Assert.assertTrue( e.getMessage().contains( "violates 
unique constraint" ) );
            }
        });
    }

    @Test
    public void testUpdate() {
        running( fakeApplication(), () -> {
            aragornDatabaseConnection.setConnection( DB.getConnection( "mydb
" ) );

            // Insert the first template (should succeed)
            EmailTemplate emailTemplate = new EmailTemplate();
            emailTemplate.setEmailTemplateMnemonic( EmailTemplateMnemonic.
TEST_EMAIL_TEMPLATE.getValue() );
            emailTemplate.setFromEmail( "[email protected]" );
            emailTemplate.setFromName( "Josh Padnick" );
            emailTemplate.setMessageBody( "Hello, this is an email!" );
            emailTemplate.setMessageSubject( "Testing!" );
            emailTemplate.setMetaDescription( "Description here" );
            emailTemplate.setMetaTitle( "Test Email" );
            emailTemplateDao.setEmailTemplate( emailTemplate );

            try {
                emailTemplateDao.insert();
            } catch (SQLException e) {
                Assert.fail("Failed to insert first EmailTemplate");
            }

            // Now update it
            EmailTemplate emailTemplateUpdated = new EmailTemplate();
            emailTemplateUpdated.setEmailTemplateMnemonic( 
EmailTemplateMnemonic.TEST_EMAIL_TEMPLATE.getValue() );
            emailTemplateUpdated.setFromEmail( "[email protected]" );
            emailTemplateUpdated.setFromName( "Joshua Padnick" );
            emailTemplateUpdated.setMessageBody( "Hello!" );
            emailTemplateUpdated.setMessageSubject( "Hola!" );
            emailTemplateUpdated.setMetaDescription( "Description here" );
            emailTemplateUpdated.setMetaTitle( "Test Email" );
            emailTemplateDao.setEmailTemplate( emailTemplateUpdated );

            EmailTemplate emailTemplateUpdatedResponse = new EmailTemplate
();

            try {
                emailTemplateUpdatedResponse = emailTemplateDao.update();
            } catch (SQLException e) {
                Assert.fail();
            }

            assertThat( emailTemplateUpdatedResponse.getFromEmail().equals( 
"[email protected]" ) );
            assertThat( emailTemplateUpdatedResponse.getFromName().equals( 
"Joshua 
Padnick" ) );
        });
    }


    @After
    public void teardown() {
        running( fakeApplication(), () -> {
            aragornDatabaseConnection.setConnection( DB.getConnection( 
"mydb" ) );

            try {
                emailTemplateDao.delete( 
EmailTemplateMnemonic.TEST_EMAIL_TEMPLATE 
);
            } catch (SQLException e) {
                Assert.fail();
            }
        });
    }


}

-- 
You received this message because you are subscribed to the Google Groups "jOOQ 
User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to