【问题标题】:How to test generic abstract class with @Autowired fields?如何使用@Autowired 字段测试通用抽象类?
【发布时间】:2019-07-25 14:16:31
【问题描述】:

我有包含@Autowired 字段的通用抽象类 AbstractBaseEntityGenericDao。它工作得很好,直到我不得不为它编写一个单元测试,而不是在扩展它的类的所有测试中复制相同的代码。现在我在想...是否可以为此类编写单元/集成测试?

@Repository
@Transactional
public abstract class AbstractBaseEntityGenericDao<T extends BaseEntity> {

    private Class<T> classInstance;

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public final void setClassInstance(Class<T> clasInstance) {
        this.classInstance = clasInstance;
    }

    public void create(@NonNull T entity) {
        Session session = sessionFactory.getCurrentSession();
        session.save(entity);
    }

    public Optional<T> find(long id) {
        Session session = sessionFactory.getCurrentSession();
        return Optional.ofNullable(session.get(classInstance, id));
    }

    public void update(@NonNull T entity) {
        Session session = sessionFactory.getCurrentSession();
        session.saveOrUpdate(entity);
    }

    public void remove(@NonNull Long id) throws EntityNotFoundException {
        Session session = sessionFactory.getCurrentSession();
        session.remove(session.load(classInstance, id));
    }

    public void remove(@NonNull T entity) {
        Session session = sessionFactory.getCurrentSession();
        session.remove(entity);
    }
}

【问题讨论】:

  • @Autowired 注解描述了 SessionFactory 对象的依赖注入。你到底在写什么单元测试?你在测试AbstractBaseEntityGenericDao里面的方法吗?
  • 是的。也许它更像是一个集成测试,但无论如何......

标签: java spring junit mocking


【解决方案1】:

这很困难的原因是因为通常你不应该这样做。抽象类应该不知道它的子类如何创建SessionFactory。所以它应该看起来像:

@Repository
@Transactional
public abstract class AbstractBaseEntityGenericDao<T extends BaseEntity> {

    ...        

    protected SessionFactory sessionFactory;

    ...
}

现在你不能直接对抽象类进行单元测试,因为它不能被实例化。但是,您可以在单元测试中将其存根,并测试该存根。存根反过来将有一个受保护字段的构造函数,我们可以在单元测试中模拟出来。最后它看起来像:

public class AbstractBaseEntityGenericDaoTest {

    private class AbstractClassStub extends AbstractBaseEntityGenericDao {

        public AbstractClassStub(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }

        @Override
        public void create(BaseEntity entity) {
            super.create(entity);
        }

        @Override
        public Optional find(long id) {
            return super.find(id);
        }

        @Override
        public void update(BaseEntity entity) {
            super.update(entity);
        }

        @Override
        public void remove(@NonNull Long id) throws EntityNotFoundException {
            super.remove(id);
        }

        @Override
        public void remove(BaseEntity entity) {
            super.remove(entity);
        }
    }

    @Mock
    SessionFactory sessionFactory;

    private AbstractClassStub abstractClassStub;

    @Before
    public void before() {
        sessionFactory = mock(SessionFactory.class);
        abstractClassStub = new AbstractClassStub(sessionFactory);
    }

    @Test
    public void testWhatever() {
        abstractClassStub.find(1); //or whatever
    }
}

【讨论】:

  • 这个解决方案非常适合。谢谢。
猜你喜欢
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 2015-10-23
  • 1970-01-01
  • 2010-11-08
相关资源
最近更新 更多