diff options
author | Stephane Gamard <stephane.gamard@searchbox.com> | 2014-04-28 13:02:29 +0200 |
---|---|---|
committer | Stephane Gamard <stephane.gamard@searchbox.com> | 2014-04-28 13:02:29 +0200 |
commit | 5214de8cc260b47b130d863ddeba87b7d204239b (patch) | |
tree | 38127498ca33129d3d64ff1f58662fbf5c477db6 /sonar-core | |
parent | ccfe6cfa7a279f708d4bf8842e66f35f2221ecb0 (diff) | |
download | sonarqube-5214de8cc260b47b130d863ddeba87b7d204239b.tar.gz sonarqube-5214de8cc260b47b130d863ddeba87b7d204239b.zip |
SONAR-5237 - moved DB part of stack to sonar-core
Diffstat (limited to 'sonar-core')
11 files changed, 529 insertions, 25 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/cluster/LocalNonBlockingWorkQueue.java b/sonar-core/src/main/java/org/sonar/core/cluster/LocalNonBlockingWorkQueue.java new file mode 100644 index 00000000000..25b10c399ec --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/cluster/LocalNonBlockingWorkQueue.java @@ -0,0 +1,94 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.core.cluster; + +import org.sonar.core.cluster.WorkQueue; + +import java.io.Serializable; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class LocalNonBlockingWorkQueue implements WorkQueue{ + + private final static int WORKQUEUE_INITIAL_CAPACITY = 20; + + private ConcurrentHashMap<String, Queue<Serializable>> index; + private ConcurrentHashMap<String, Queue<Serializable>> update; + private ConcurrentHashMap<String, Queue<Serializable>> delete; + + public LocalNonBlockingWorkQueue(){ + this.index = new ConcurrentHashMap<String, Queue<Serializable>>(WORKQUEUE_INITIAL_CAPACITY); + this.update = new ConcurrentHashMap<String, Queue<Serializable>>(WORKQUEUE_INITIAL_CAPACITY); + this.delete = new ConcurrentHashMap<String, Queue<Serializable>>(WORKQUEUE_INITIAL_CAPACITY); + } + + private Integer enqueue(Map<String, Queue<Serializable>> map, String indexName, Serializable key){ + if(!map.containsKey(indexName)){ + map.put(indexName, new ConcurrentLinkedQueue<Serializable>()); + } + map.get(indexName).offer(key); + return 0; + } + + private Object dequeue(Map<String, Queue<Serializable>> map, String indexName){ + return (map.containsKey(indexName))? + map.get(indexName).poll(): + null; + } + + @Override + public Integer enqueInsert(String indexName, Serializable key) { + return this.enqueue(index, indexName, key); + } + + @Override + public Integer enqueUpdate(String indexName, Serializable key) { + return this.enqueue(update, indexName, key); + } + + @Override + public Integer enqueDelete(String indexName, Serializable key) { + return this.enqueue(delete, indexName, key); + } + + @Override + public Object dequeInsert(String indexName) { + return this.dequeue(index, indexName); + } + + @Override + public Object dequeUpdate(String indexName) { + return this.dequeue(update, indexName); + } + + @Override + public Object dequeDelete(String indexName) { + return this.dequeue(delete, indexName); + } + + @Override + public Status getStatus(Integer workId) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/sonar-core/src/main/java/org/sonar/core/cluster/WorkQueue.java b/sonar-core/src/main/java/org/sonar/core/cluster/WorkQueue.java new file mode 100644 index 00000000000..e3790f642b9 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/cluster/WorkQueue.java @@ -0,0 +1,43 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.core.cluster; + +import java.io.Serializable; + +public interface WorkQueue { + + Integer enqueInsert(String indexName, Serializable key); + + Integer enqueUpdate(String indexName, Serializable key); + + Integer enqueDelete(String indexName, Serializable key); + + Object dequeInsert(String indexName); + + Object dequeUpdate(String indexName); + + Object dequeDelete(String indexName); + + Status getStatus(Integer workId); + + interface Status { + + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/db/BaseDao.java b/sonar-core/src/main/java/org/sonar/core/db/BaseDao.java new file mode 100644 index 00000000000..e10bbf6cfdb --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/db/BaseDao.java @@ -0,0 +1,113 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.core.db; + +import org.apache.ibatis.session.SqlSession; +import org.sonar.core.cluster.WorkQueue; +import org.sonar.core.persistence.MyBatis; + +import java.io.Serializable; + +public abstract class BaseDao<E extends Dto<K>, K extends Serializable, M extends Dao<E,K>> + implements Dao<E, K> { + + protected MyBatis mybatis; + private WorkQueue queue; + + protected BaseDao(WorkQueue workQueue, MyBatis myBatis) { + this.mybatis = myBatis; + this.queue = workQueue; + } + + protected abstract String getIndexName(); + + protected abstract Class<M> getMapperClass(); + + private M getMapper(SqlSession session) { + return session.getMapper(getMapperClass()); + } + + protected void enqueInsert(K key) { + this.queue.enqueInsert(this.getIndexName(), key); + } + + protected void enqueUpdate(K key) { + this.queue.enqueUpdate(this.getIndexName(), key); + } + + protected void enqueDelete(K key) { + this.queue.enqueDelete(this.getIndexName(), key); + } + + protected MyBatis getMyBatis(){ + return this.mybatis; + } + + @Override + @SuppressWarnings("unchecked") + public E getByKey(K key) { + E item = null; + SqlSession session = getMyBatis().openSession(); + item = getMapper(session).getByKey(key); + MyBatis.closeQuietly(session); + return item; + } + + @Override + public void update(E item) { + SqlSession session = getMyBatis().openSession(); + try { + getMapper(session).update(item); + session.commit(); + this.enqueUpdate(item.getKey()); + } finally { + MyBatis.closeQuietly(session); + } + } + + @Override + public void insert(E item) { + SqlSession session = getMyBatis().openSession(); + try { + getMapper(session).insert(item); + session.commit(); + this.enqueInsert(item.getKey()); + } finally { + MyBatis.closeQuietly(session); + } + } + + @Override + public void delete(E item) { + this.deleteByKey(item.getKey()); + } + + @Override + public void deleteByKey(K key) { + SqlSession session = getMyBatis().openSession(); + try { + getMapper(session).deleteByKey(key); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + this.enqueDelete(key); + } + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/db/Dao.java b/sonar-core/src/main/java/org/sonar/core/db/Dao.java new file mode 100644 index 00000000000..458d2b703e2 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/db/Dao.java @@ -0,0 +1,39 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.core.db; + +import java.io.Serializable; +import java.util.Collection; + +public interface Dao<E extends Dto<K>, K extends Serializable> { + + public E getByKey(K key); + + public void update(E item); + + public void insert(E item); + + public void delete(E item); + + public void deleteByKey(K key); + + public Collection<K> insertsSince(Long timestamp); + +} diff --git a/sonar-core/src/main/java/org/sonar/core/db/Dto.java b/sonar-core/src/main/java/org/sonar/core/db/Dto.java new file mode 100644 index 00000000000..2ac53d71222 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/db/Dto.java @@ -0,0 +1,28 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.core.db; + +import java.io.Serializable; + +public interface Dto<K extends Serializable> { + + K getKey(); + +} diff --git a/sonar-core/src/main/java/org/sonar/core/rule/RuleConstants.java b/sonar-core/src/main/java/org/sonar/core/rule/RuleConstants.java new file mode 100644 index 00000000000..636a6dcd67c --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/rule/RuleConstants.java @@ -0,0 +1,26 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.core.rule; + +public interface RuleConstants { + + public static final String INDEX_NAME = "rules"; + public static final String ES_TYPE = "rule"; +} diff --git a/sonar-core/src/main/java/org/sonar/core/rule/RuleDao.java b/sonar-core/src/main/java/org/sonar/core/rule/RuleDao.java index 3b5677fc9b9..1c87168d8b5 100644 --- a/sonar-core/src/main/java/org/sonar/core/rule/RuleDao.java +++ b/sonar-core/src/main/java/org/sonar/core/rule/RuleDao.java @@ -24,6 +24,8 @@ import org.apache.ibatis.session.SqlSession; import org.sonar.api.BatchComponent; import org.sonar.api.ServerComponent; import org.sonar.api.rule.RuleKey; +import org.sonar.core.cluster.WorkQueue; +import org.sonar.core.db.BaseDao; import org.sonar.core.persistence.MyBatis; import javax.annotation.CheckForNull; @@ -33,12 +35,22 @@ import java.util.List; import static com.google.common.collect.Lists.newArrayList; -public class RuleDao implements BatchComponent, ServerComponent { +public class RuleDao extends BaseDao<RuleDto, RuleKey, RuleMapper> + implements BatchComponent, ServerComponent { - private MyBatis mybatis; - public RuleDao(MyBatis mybatis) { - this.mybatis = mybatis; + public RuleDao(MyBatis mybatis, WorkQueue queue) { + super(queue, mybatis); + } + + @Override + protected String getIndexName() { + return RuleConstants.INDEX_NAME; + } + + @Override + protected Class<RuleMapper> getMapperClass() { + return RuleMapper.class; } public List<RuleDto> selectAll() { @@ -131,29 +143,18 @@ public class RuleDao implements BatchComponent, ServerComponent { getMapper(session).update(rule); } - public void update(RuleDto rule) { - SqlSession session = mybatis.openSession(); - try { - update(rule, session); - session.commit(); - } finally { - MyBatis.closeQuietly(session); - } - } +// public RuleDto update(RuleDto rule) { +// return super.update(rule); +// } +// +// public RuleDto insert(RuleDto ruleToInsert) { +// return super.insert(ruleToInsert); +// } public void insert(RuleDto ruleToInsert, SqlSession session) { getMapper(session).insert(ruleToInsert); } - public void insert(RuleDto ruleToInsert) { - SqlSession session = mybatis.openSession(); - try { - insert(ruleToInsert, session); - session.commit(); - } finally { - MyBatis.closeQuietly(session); - } - } public void insert(Collection<RuleDto> rules) { SqlSession session = mybatis.openBatchSession(); @@ -307,4 +308,10 @@ public class RuleDao implements BatchComponent, ServerComponent { } return dtos; } + + @Override + public Collection<RuleKey> insertsSince(Long timestamp) { + // TODO Auto-generated method stub + return null; + } } diff --git a/sonar-core/src/main/java/org/sonar/core/rule/RuleDto.java b/sonar-core/src/main/java/org/sonar/core/rule/RuleDto.java index 8bb8f4e38b5..78dd41c99a5 100644 --- a/sonar-core/src/main/java/org/sonar/core/rule/RuleDto.java +++ b/sonar-core/src/main/java/org/sonar/core/rule/RuleDto.java @@ -19,6 +19,9 @@ */ package org.sonar.core.rule; +import org.sonar.api.rule.RuleKey; + +import org.sonar.core.db.Dto; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ReflectionToStringBuilder; @@ -30,7 +33,7 @@ import javax.annotation.Nullable; import java.util.Date; -public final class RuleDto { +public final class RuleDto implements Dto<RuleKey>{ public static final Integer DISABLED_CHARACTERISTIC_ID = -1; @@ -61,6 +64,12 @@ public final class RuleDto { private Date createdAt; private Date updatedAt; + @Override + public RuleKey getKey() { + return RuleKey.of(this.getRepositoryKey(), this.getRuleKey()); + } + + @Deprecated public Integer getId() { return id; } diff --git a/sonar-core/src/main/java/org/sonar/core/rule/RuleMapper.java b/sonar-core/src/main/java/org/sonar/core/rule/RuleMapper.java index e31b14e04aa..536071017eb 100644 --- a/sonar-core/src/main/java/org/sonar/core/rule/RuleMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/rule/RuleMapper.java @@ -21,10 +21,12 @@ package org.sonar.core.rule; import org.apache.ibatis.annotations.Param; import org.sonar.api.rule.RuleKey; +import org.sonar.core.db.Dao; import java.util.List; -public interface RuleMapper { +public interface RuleMapper extends Dao<RuleDto, RuleKey>{ + List<RuleDto> selectAll(); List<RuleDto> selectEnablesAndNonManual(); diff --git a/sonar-core/src/test/java/org/sonar/core/cluster/LocalNonBlockingWorkQueueTest.java b/sonar-core/src/test/java/org/sonar/core/cluster/LocalNonBlockingWorkQueueTest.java new file mode 100644 index 00000000000..c352f14cb44 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/cluster/LocalNonBlockingWorkQueueTest.java @@ -0,0 +1,138 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.core.cluster; + +import org.sonar.core.cluster.LocalNonBlockingWorkQueue; + +import org.junit.Test; + +import java.io.Serializable; +import java.util.Map; + +import static org.fest.assertions.Assertions.assertThat; + + +public class LocalNonBlockingWorkQueueTest { + + private static final String WORKING_INDEX = "working_index"; + private static final String NON_WORKING_INDEX = "non_working_index"; + + @Test + public void test_insert_queue(){ + LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue(); + + assertThat(queue.dequeInsert(WORKING_INDEX)).isNull(); + assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull(); + + queue.enqueInsert(WORKING_INDEX, new Integer(0)); + assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull(); + + Object dequeued = queue.dequeInsert(WORKING_INDEX); + assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull(); + assertThat(queue.dequeInsert(WORKING_INDEX)).isNull(); + + assertThat(dequeued).isEqualTo(new Integer(0)); + } + + @Test + public void test_update_queue(){ + LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue(); + + assertThat(queue.dequeUpdate(WORKING_INDEX)).isNull(); + assertThat(queue.dequeUpdate(NON_WORKING_INDEX)).isNull(); + + queue.enqueUpdate(WORKING_INDEX, new Integer(0)); + assertThat(queue.dequeUpdate(NON_WORKING_INDEX)).isNull(); + + Object dequeued = queue.dequeUpdate(WORKING_INDEX); + assertThat(queue.dequeUpdate(NON_WORKING_INDEX)).isNull(); + assertThat(queue.dequeUpdate(WORKING_INDEX)).isNull(); + + assertThat(dequeued).isEqualTo(new Integer(0)); + } + + @Test + public void test_delete_queue(){ + LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue(); + + assertThat(queue.dequeDelete(WORKING_INDEX)).isNull(); + assertThat(queue.dequeDelete(NON_WORKING_INDEX)).isNull(); + + queue.enqueDelete(WORKING_INDEX, new Integer(0)); + assertThat(queue.dequeDelete(NON_WORKING_INDEX)).isNull(); + + Object dequeued = queue.dequeDelete(WORKING_INDEX); + assertThat(queue.dequeDelete(NON_WORKING_INDEX)).isNull(); + assertThat(queue.dequeDelete(WORKING_INDEX)).isNull(); + + assertThat(dequeued).isEqualTo(new Integer(0)); + } + + @Test + public void test_enque_seralizable_object(){ + + LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue(); + + class NonSerializable implements Serializable{ + private Object var1; + private Map<String, Object> objs; + } + + NonSerializable nonSer = new NonSerializable(); + assertThat(queue.enqueInsert(WORKING_INDEX, nonSer)).isNotNull(); + + Object dequeued = queue.dequeInsert(WORKING_INDEX); + assertThat(queue.dequeInsert(NON_WORKING_INDEX)).isNull(); + + assertThat(dequeued).isNotNull(); + assertThat(dequeued.getClass()).isEqualTo(NonSerializable.class); + } + + @Test + public void test_under_queue_capacity(){ + LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue(); + + for(int i = 0; i < 10; i++){ + assertThat(queue.enqueDelete(WORKING_INDEX, i)).isNotNull(); + } + + for(int i = 0; i < 10; i++){ + assertThat(queue.dequeDelete(WORKING_INDEX)).isNotNull(); + } + assertThat(queue.dequeDelete(WORKING_INDEX)).isNull(); + + } + + @Test + public void test_over_queue_capacity(){ + LocalNonBlockingWorkQueue queue = new LocalNonBlockingWorkQueue(); + + for(int i = 0; i < 100; i++){ + assertThat(queue.enqueDelete(WORKING_INDEX, i)).isNotNull(); + } + + for(int i = 0; i < 100; i++){ + assertThat(queue.dequeDelete(WORKING_INDEX)).isNotNull(); + } + assertThat(queue.dequeDelete(WORKING_INDEX)).isNull(); + + } + +} diff --git a/sonar-core/src/test/java/org/sonar/core/rule/RuleDaoTest.java b/sonar-core/src/test/java/org/sonar/core/rule/RuleDaoTest.java index 6386962c054..8b6aaf45095 100644 --- a/sonar-core/src/test/java/org/sonar/core/rule/RuleDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/rule/RuleDaoTest.java @@ -19,6 +19,8 @@ */ package org.sonar.core.rule; +import org.sonar.core.cluster.WorkQueue; + import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; @@ -34,6 +36,8 @@ import org.sonar.core.persistence.AbstractDaoTestCase; import java.util.List; +import static org.mockito.Mockito.mock; + import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; @@ -43,7 +47,8 @@ public class RuleDaoTest extends AbstractDaoTestCase { @Before public void createDao() throws Exception { - dao = new RuleDao(getMyBatis()); + WorkQueue queue = mock(WorkQueue.class); + dao = new RuleDao(getMyBatis(), queue); } @Test |