简体   繁体   English

如何使用@Autowired 字段测试通用抽象类?

[英]How to test generic abstract class with @Autowired fields?

I have generic abstract class AbstractBaseEntityGenericDao which contains @Autowired field.我有包含@Autowired 字段的通用抽象类 AbstractBaseEntityGenericDao。 It worked perfectly until I had to write a unit test for it, to not duplicate the same code inside all tests for classes which extends it.它工作得很好,直到我不得不为它编写单元测试,不要在扩展它的类的所有测试中复制相同的代码。 And now I'm thinking...Is it possible to write a unit/integration test for such class?现在我在想……是否可以为此类课程编写单元/集成测试?

@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);
    }
}

The reason this is difficult is because generally you should not be doing this.这很困难的原因是因为通常你不应该这样做。 The abstract class should have no knowledge of how its child creates SessionFactory .抽象类应该不知道它的子类如何创建SessionFactory so instead it should look something like:所以它应该看起来像:

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

    ...        

    protected SessionFactory sessionFactory;

    ...
}

Now you CANNOT directly unit test a abstract class as it can not be instantiated.现在你不能直接对抽象类进行单元测试,因为它不能被实例化。 you can however stub it out in a unit test, and test that stub.但是,您可以在单元测试中将其存根,然后测试该存根。 The stub in turn will have a constructor for the protected field which we can mock out in the unit test.存根反过来将有一个受保护字段的构造函数,我们可以在单元测试中模拟它。 In the end it would look like:最后它看起来像:

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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM