在 ObjectMother 中自动装配 jdbcTemplate 以进行 junit 4 集成测试

Autowire jdbcTemplate in ObjectMother for a junit 4 integration test

我想知道我是否可以在 ObjectMother 中以某种方式自动装配 jdbcTemplate 以进行 junit 4 集成测试。

测试的目的是测试如果你给一个员工附加一个文件,你不能在之后附加一个同名的文件。 为此,我使用 jdbcTemplate 创建了一个 EmployeeMother,它有一个创建 Employee 的方法和一个插入它的方法。如果我尝试在 EmployeeMother 中自动装配 jdbcTemplate,它为空(第一次更新时测试 returns NPE)。看来我只能从测试本身访问 applicationContexts。

目前我从测试本身设置它,但我不想这样做,因为我将为不同的对象创建更多的 ObjectMothers,并且不想为所有对象设置 jdbcTemplate。

下面是两个类(我从包中删除了公司名称并导入):

员工妈妈:

    package com.domain.objMother;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.jdbc.core.JdbcTemplate;

    import com.domain.vo.Company;
    import com.domain.vo.Contact;
    import com.domain.vo.Employee;
    import com.domain.vo.Identification;
    import com.domain.vo.Role;

    public class EmployeeMother {
        private final Log log = LogFactory.getLog(getClass());

        protected JdbcTemplate jdbcTemplate;
        private Employee empJohnDoe;

        /**
         * 
         * @return returns an admin user with username djohn
         */
        public Employee getEmpJohnDoe() {
            empJohnDoe = new Employee();
            empJohnDoe.setUserName("djohn");

            Role role = new Role();
            //as only the id of the role is not nullable I set it as 1 = admin
            role.setId(new Long(1));
            empJohnDoe.setRole(role);
            empJohnDoe.setCompany(new Company());

            Identification identity = new Identification();
            identity.setFirstName("John");
            identity.setLastName("Doe");
            identity.setContact(new Contact());
            empJohnDoe.setIdentity(identity);

            return empJohnDoe;
        }

        public void setEmpJohnDoe(Employee empJohnDoe) {
            this.empJohnDoe = empJohnDoe;
        }

        /**
         * Important! this insert does not cover some details of the Employee:
         * It inserts null in the following columns:
         * pswd,
         * image,
         * cnt_id, - should be a list of associated contacts
         * salt,
         * is_active,
         * default_work_hours
         * The insert in TAB_IDENTIFICATIONS triggers TRIG_IDNT that inserts stuff in an audit table
         * For it to work we need to register a logged user
         * That's why we call PAC_SECURITY.PRO_SETCTX('emp_user_name','adminUserName'); (i used an admin)
         * I preferred doing this rather than inserting djohn in TAB_EMPLOYEES, 
         * registering djohn as logged then inserting an identity in TAB_IDENTIFICATIONS
         * and then updating djohn with the new identity
         * @param emp - Employee to be inserted
         */
        public void insert(Employee emp){
            jdbcTemplate.update("call PAC_SECURITY.PRO_SETCTX('emp_user_name','adminUserName')");

            Long identityId = jdbcTemplate.queryForObject("select max(ti.ID)+1 from tab_identifications ti", Long.class);
            emp.getIdentity().setId(identityId);

            jdbcTemplate.update(""+
                "   insert into tab_identifications ("+
                "       id, first_name, middle_name, last_name, cnp, ci_char, ci_number, birth_date, invalidity,"+
                "       cas_name, ci_issue_date, ci_issuer, cnt_id"+
                "   )" +
                "   values (?,?,?,?,?,?,?,?,?,?,?,?,?)",
                new Object[]{emp.getIdentity().getId(), emp.getIdentity().getFirstName(), emp.getIdentity().getMiddleName(),
                             emp.getIdentity().getLastName(), emp.getIdentity().getCnp(), emp.getIdentity().getIdCardSerial(),
                             emp.getIdentity().getIdCardNumber(), emp.getIdentity().getBirthDate(), 
                             emp.getIdentity().getInvalidity(), emp.getIdentity().getCAS(), emp.getIdentity().getCiIssueDate(),
                             emp.getIdentity().getCiIssuer(), emp.getIdentity().getContact().getId()}
            );      

            Long id = jdbcTemplate.queryForObject("select max(te.ID)+1 from tab_employees te", Long.class);
            emp.setId(id);
            jdbcTemplate.update(""+
                "   insert into tab_employees (id, user_name, code, pswd, idnt_id, role_id, comp_id, image, "+
                "       hire_date, cnt_id, salt, is_expired, is_active, default_work_hours "+
                "   )" +
                "   values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
                new Object[]{emp.getId(), emp.getUserName(), emp.getCode(), null, emp.getIdentity().getId(),
                             emp.getRole().getId(), emp.getCompany().getId(), null, emp.getHireDate(),
                             null, null, emp.getIsExpired(), null, null
                }
            );
        }

        public JdbcTemplate getJdbcTemplate() {
            return jdbcTemplate;
        }

        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    }

HomeEmployeeServiceImplIntegrationTest:

    package com.employee.service.impl;

    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

    import com.domain.vo.Document;
    import com.domain.vo.Employee;
    import com.domain.objMother.EmployeeMother;
    import com.employee.service.HomeEmployeeService;
    import com.util.annotations.TransactionalDevTest;

    import static org.junit.Assert.*;

    @RunWith(SpringJUnit4ClassRunner.class)
    @TransactionalDevTest
    public class HomeEmployeeServiceImplIntegrationTest {

        @Autowired
        protected JdbcTemplate jdbcTemplate;

        @Autowired
        HomeEmployeeService homeEmployeeService;

        EmployeeMother empMother = new EmployeeMother();
        Employee empJohnDoe;

        @Before
        public void beforeEachTest() throws Exception {
            empMother.setJdbcTemplate(jdbcTemplate);
            empJohnDoe = empMother.getEmpJohnDoe();
            empMother.insert(empJohnDoe);
        }

        /**
         * You should not be able to add a document with the same name
         * <code>uploadDocument</code> should not insert the document if it has the same name 
         */
         @Test
         public void shouldNotBeAbleToAddSameDoc(){
             Document doc = new Document();
             Long id = jdbcTemplate.queryForObject("select max(td.ID)+1 from tab_documents td", Long.class);
             doc.setId(id);
             doc.setFileName("SameOldDocument");

             homeEmployeeService.uploadDocument(empJohnDoe.getIdentity(), doc);

             id = jdbcTemplate.queryForObject("select max(td.ID)+1 from tab_documents td", Long.class);
             doc.setId(id);
             homeEmployeeService.uploadDocument(empJohnDoe.getIdentity(), doc);

             Long docNo = jdbcTemplate.queryForObject("select count(id) from tab_documents td where doc_file_name = '" + doc.getFileName() + "'", Long.class);

             if(docNo.compareTo(new Long(2)) == 0){
                 assertEquals("I was able to add a document twice with the same name!", new Long(1), docNo);
             }
             else{
                 assertEquals("Something went wrong when adding two documents with the same name! The document should be added once or twice, but the result is different!", new Long(1), docNo);
             }
        }

TransactionalDevTest 是我定义所有使用的 applicationContext 的地方。 上面的代码有效,但我想分离 EmployeeMother 的代码并添加 IdentificationMother 和可能的 DocumentMother 每个及其对象并插入。我也不想为每个 ObjectMother 设置 jdbcTemplate(事情可能变得模棱两可,一些设置来自测试的 jdbcTemplate,一些来自另一个 ObjectMother)。

提前致谢。

我得到了一位同事的帮助,这就是我所做的:

我为 ObjectMothers 做了注释:

package com.util.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ObjectMother {}

我将此注释添加到我的 EmployeeMother:

@ObjectMother
public class EmployeeMother {

并在 EmployeeMother 中自动装配我的 jdbcTemplate(还删除了 getter 和 setter)

@Autowired
protected JdbcTemplate jdbcTemplate;

我添加到一个applicationContext:

xmlns:

xmlns:context="http://www.springframework.org/schema/context"

具有架构位置

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

<context:component-scan base-package="com.domain.objMother">
    <context:include-filter type="annotation" expression="com.util.annotations.ObjectMother"/>
</context:component-scan>

这将搜索所有使用 ObjectMother 注释的 classes 并将它们添加到 applicationContext(这样您就不必一一添加它们)。

最后,我在 HomeEmployeeServiceImplIntegrationTest 中使用了自动装配的 EmployeeMother,并在同一 class:

中删除了 EmployeeMother 对 jdbcTemplate 的任何引用
@Autowired
EmployeeMother empMother;

最终 classes:

员工母亲:

    package com.domain.objMother;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;

    import com.domain.vo.Company;
    import com.domain.vo.Contact;
    import com.domain.vo.Employee;
    import com.domain.vo.Identification;
    import com.domain.vo.Role;
    import com.util.annotations.ObjectMother;

    @ObjectMother
    public class EmployeeMother {
        private final Log log = LogFactory.getLog(getClass());

        @Autowired
        protected JdbcTemplate jdbcTemplate;

        private Employee empJohnDoe;

        /**
         * 
         * @return returns an admin user with username djohn
         */
        public Employee getEmpJohnDoe() {
            empJohnDoe = new Employee();
            empJohnDoe.setUserName("djohn");

            Role role = new Role();
            //as only the id of the role is not nullable I set it as 1 = admin
            role.setId(new Long(1));
            empJohnDoe.setRole(role);
            empJohnDoe.setCompany(new Company());

            Identification identity = new Identification();
            identity.setFirstName("John");
            identity.setLastName("Doe");
            identity.setContact(new Contact());
            empJohnDoe.setIdentity(identity);

            return empJohnDoe;
        }

        public void setEmpJohnDoe(Employee empJohnDoe) {
            this.empJohnDoe = empJohnDoe;
        }

        /**
         * Important! this insert does not cover some details of the Employee:
         * It inserts null in the following columns:
         * pswd,
         * image,
         * cnt_id, - should be a list of associated contacts
         * salt,
         * is_active,
         * default_work_hours
         * The insert in TAB_IDENTIFICATIONS triggers TRIG_IDNT that inserts stuff in an audit table
         * For it to work we need to register a logged user
         * That's why we call PAC_SECURITY.PRO_SETCTX('emp_user_name','adminUserName'); (i used an admin)
         * I preferred doing this rather than inserting djohn in TAB_EMPLOYEES, 
         * registering djohn as logged then inserting an identity in TAB_IDENTIFICATIONS
         * and then updating djohn with the new identity
         * @param emp - Employee to be inserted
         */
        public void insert(Employee emp){
            jdbcTemplate.update("call PAC_SECURITY.PRO_SETCTX('emp_user_name','adminUserName')");

            Long identityId = jdbcTemplate.queryForObject("select max(ti.ID)+1 from tab_identifications ti", Long.class);
            emp.getIdentity().setId(identityId);

            jdbcTemplate.update(""+
                "   insert into tab_identifications ("+
                "       id, first_name, middle_name, last_name, cnp, ci_char, ci_number, birth_date, invalidity,"+
                "       cas_name, ci_issue_date, ci_issuer, cnt_id"+
                "   )" +
                "   values (?,?,?,?,?,?,?,?,?,?,?,?,?)",
                new Object[]{emp.getIdentity().getId(), emp.getIdentity().getFirstName(), emp.getIdentity().getMiddleName(),
                             emp.getIdentity().getLastName(), emp.getIdentity().getCnp(), emp.getIdentity().getIdCardSerial(),
                             emp.getIdentity().getIdCardNumber(), emp.getIdentity().getBirthDate(), 
                             emp.getIdentity().getInvalidity(), emp.getIdentity().getCAS(), emp.getIdentity().getCiIssueDate(),
                             emp.getIdentity().getCiIssuer(), emp.getIdentity().getContact().getId()}
            );      

            Long id = jdbcTemplate.queryForObject("select max(te.ID)+1 from tab_employees te", Long.class);
            emp.setId(id);
            jdbcTemplate.update(""+
                "   insert into tab_employees (id, user_name, code, pswd, idnt_id, role_id, comp_id, image, "+
                "       hire_date, cnt_id, salt, is_expired, is_active, default_work_hours "+
                "   )" +
                "   values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
                new Object[]{emp.getId(), emp.getUserName(), emp.getCode(), null, emp.getIdentity().getId(),
                             emp.getRole().getId(), emp.getCompany().getId(), null, emp.getHireDate(),
                             null, null, emp.getIsExpired(), null, null
                }
            );
        }
    }

HomeEmployeeServiceImplIntegrationTest:

    package com.employee.service.impl;

    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

    import com.domain.vo.Document;
    import com.domain.vo.Employee;
    import com.domain.objMother.EmployeeMother;
    import com.employee.service.HomeEmployeeService;
    import com.util.annotations.TransactionalDevTest;

    import static org.junit.Assert.*;

    @RunWith(SpringJUnit4ClassRunner.class)
    @TransactionalDevTest
    public class HomeEmployeeServiceImplIntegrationTest {

        @Autowired
        protected JdbcTemplate jdbcTemplate;

        @Autowired
        HomeEmployeeService homeEmployeeService;

        @Autowired
        EmployeeMother empMother;

        Employee empJohnDoe;

        @Before
        public void beforeEachTest() throws Exception {
            empJohnDoe = empMother.getEmpJohnDoe();
            empMother.insert(empJohnDoe);
        }

        /**
         * You should not be able to add a document with the same name
         * <code>uploadDocument</code> should not insert the document if it has the same name 
         */
        @Test
        public void shouldNotBeAbleToAddSameDoc(){
            Document doc = new Document();
            Long id = jdbcTemplate.queryForObject("select max(td.ID)+1 from tab_documents td", Long.class);
            doc.setId(id);
            doc.setFileName("SameOldDocument");

            homeEmployeeService.uploadDocument(empJohnDoe.getIdentity(), doc);

            id = jdbcTemplate.queryForObject("select max(td.ID)+1 from tab_documents td", Long.class);
            doc.setId(id);
            homeEmployeeService.uploadDocument(empJohnDoe.getIdentity(), doc);

            Long docNo = jdbcTemplate.queryForObject("select count(id) from tab_documents td where doc_file_name = '" + doc.getFileName() + "'", Long.class);

            if(docNo.compareTo(new Long(2)) == 0){
                assertEquals("I was able to add a document twice with the same name!", new Long(1), docNo);
            }
            else{
                assertEquals("Something went wrong when adding two documents with the same name! The document should be added once or twice, but the result is different!", new Long(1), docNo);
            }
        }
    }