spring单元测试

环境搭建

参考《SpringDataJpa基本使用》。

DAO测试

新建一个测试基类,后续所有的测试类继承该类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
@TransactionConfiguration(transactionManager = "transactionManager",defaultRollback = true)
@Transactional
public class BaseSpringTest {
}
public class UserDaoTest extends BaseSpringTest {
    private final Logger logger = LoggerFactory.getLogger(UserDaoTest.class);
    @Autowired
    private UserDao userDao;
    @Test
    public void testSave() {
        logger.info("testSave method in UserDaoTest");
        User user = new User();
        user.setName("test");
        user.setBirthday(new Date());
        user = this.userDao.save(user);
        assert user.getId() > 0;
        dbUserId = user.getId();
    }
}    

注意:dao的测试一定不能污染数据库,这里配置了TransactionConfiguration,在测试方法执行完毕后回滚事务。

Service测试

service层的测试通常依赖dao层,对于dao的依赖,使用mock框架mock出相应的bean,重心放在service方法的逻辑处理是否正确。
参考:《springockito-annotations做spring的单元测试》

Controller测试

参考Spring Controller单元测试

外部接口测试

1.mock外部依赖;
2.新建被测试外部依赖接口service的实现(在test/java/src),使用单元测试的spring配置文件。

多线程测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class MultiThreadServiceTest {
    private final Logger logger = LoggerFactory.getLogger(MultiThreadServiceTest.class);
    @Autowired
    private UserService userService;
    @Test
    public void multithreadSaveTest() throws InterruptedException {
        for (int i=0;i<10;i++) {
            Thread thread = new Thread(new WorkerTask());
            thread.start();
            latch.countDown(); // 线程启动后将latch数量减一,在WorkTask中会等待latch数量为0时执行数据库插入和查询操作。即保证所有线程同时执行数据库插入和查询操作。
        }
        // 这里要休眠一定时间,否则会导致所有WorkTask都没有执行。
        // 因为Junit将测试方法执行完毕就退出了,这时候子线程其实还没开始执行。
        Thread.sleep(3000L);
    }
    @After
    public void teadDown() {
        // 执行数据库清理工作。在多线程环境,在单元测试类上加入@Transactional并没有用,只对被测试方法本身所在的线程(主线程)有用,其他线程无效。
        // 所以这里在单元测试执行完毕后,对数据库做清理工作。
        userService.deleteAll(dbIds);
    }
    private CountDownLatch latch = new CountDownLatch(10);
    private Collection<Long> dbIds = new ArrayList<>();
    class WorkerTask implements Runnable {
        @Override
        public void run() {
            try {
                latch.await(); // 等待所有线程准备就绪同时执行数据库插入操作。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            User user = new User();
            user.setName("test");
            user.setBirthday(new Date());
            user = userService.save(user);
            assert user.getId() > 0;
            dbIds.add(user.getId());
            user = userService.findById(user.getId());
            logger.info("user:{}",user);
            Assert.assertNotNull(user);
            Assert.assertEquals("test",user.getName());
        }
    }
}

注意:多线程环境单元测试,就算在测试类上加入@Transactional注解,数据库操作也是不会回滚的。原因可以查看代码注释,所以需要手动执行清理操作。

你可能感兴趣的:(spring单元测试)