单元测试框架对比

xiaoxiao2021-02-28  64

单元测试框架对比

主要小试了下junit + mockito 及 testng + jmockit两种ut及mock搭配方式。做下简单对比,当做笔记。 - junit + mockito - testng + jmockit


junit + mockito

依赖:

<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>${mockito-core.version}</version> </dependency>

同spring结合,BaseTest类。继承AbstractTransactionalJUnit4SpringContextTests 加入了事务。

import org.junit.Before; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; import org.springframework.context.ApplicationContextAware; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(locations = { "classpath:spring-test.xml" }) @RunWith(SpringJUnit4ClassRunner.class) public class BaseTest extends AbstractTransactionalJUnit4SpringContextTests implements ApplicationContextAware { @Before public void setup() { /** Initializes objects annotated with Mockito annotations for given testClass */ MockitoAnnotations.initMocks(this); } }

test子类。 简单说明:leaseBiz是业务逻辑层,调用leaseService层去查询数据库。

package com.unifirst.biz; import java.math.BigDecimal; import java.util.Date; import javax.annotation.Resource; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mockito; import org.mockito.Spy; import org.springframework.test.util.ReflectionTestUtils; import com.unifirst.BaseTest; import com.unifirst.model.po.LeaseRecord; import com.unifirst.model.ro.LeaseDetailResp; import com.unifirst.service.LeaseService; /** * Created by unifirst on 2018/3/13. */ public class LeaseTest extends BaseTest { @Spy private LeaseService leaseService; @Resource @InjectMocks private LeaseBiz leaseBiz; @Before public void init() { LeaseRecord leaseRecord = new LeaseRecord(); leaseRecord.setTotalAmount(BigDecimal.ONE); leaseRecord.setEndTime(new Date()); leaseRecord.setStartTime(new Date()); leaseRecord.setUid(30030633745056L); leaseRecord.setLeaseNumber(317733346556907520L); /** 仅仅用spy + InjectMocks,无法成功注入;需要用反射方式注入 */ ReflectionTestUtils.setField(leaseBiz, "leaseService", leaseService); Mockito.when(leaseService.queryDetail(Mockito.anyLong())).thenReturn(leaseRecord); } @Test public void detailTest() { LeaseDetailResp detail = leaseBiz.detail(30030633745056L, 317733346556907520L); System.out.println(detail); } }

testng + jmockit

依赖

<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>${testng.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jmockit</groupId> <artifactId>jmockit</artifactId> <version>${jmockit.version}</version> </dependency>

test类 几处注意的地方:

无上面与spring结合的BaseTest类@Tested注解的不是interface,而是具体实现类虽然被测试代码仅仅使用到了globalConfigBiz,但其他@Resource引入的service,都需要用@Injectable注入,否则报错: java.lang.IllegalStateException: Missing @Injectable for field xxx 若被test的类有@Value注解,则同service一样要通过@Injectable注入

代码示例如下:

package com.unifirst.biz; import java.util.List; import org.testng.annotations.Test; import org.testng.collections.Lists; import com.unifirst.biz.impl.FeedBackBizImpl; import com.unifirst.model.bo.FaultTypes; import com.unifirst.service.FeedBackService; import com.unifirst.service.OpLogService; import com.wormpex.api.json.JsonUtil; import mockit.Expectations; import mockit.Injectable; import mockit.Tested; /** * Created by unifirst on 2018/3/14. */ public class FeedBackBizTest { @Tested private FeedBackBizImpl feedBackBiz; @Injectable private FeedBackService feedBackService; @Injectable private OpLogService opLogService; @Injectable private GlobalConfigBiz globalConfigBiz; @Test public void faultTypeListsTest() { new Expectations() { { FaultTypes faultTypes = new FaultTypes(); List<String> types = Lists.newArrayList("t1", "t2"); faultTypes.setTypes(types); globalConfigBiz.query(anyString); result = JsonUtil.of(faultTypes); } }; List<String> detail = feedBackBiz.faultTypeLists(); System.out.println(detail); } }

对比

junit vs testng,mockito vs jmockit 网上资料很多,不多介绍。这里只从与spring的结合性来简单对比。

junit + mockito 与spring结合性感觉更强,可以充分兼容spring的各种注解,能较完美接近项目启动后实际运行情况。可以用来做一定的业务自动化回归测试,但可能超出了ut的范围testng + jmockit 可能功能更强大,但与spring不易结合,各种注解不好兼容,如上例中直接放弃了在spring中的测试。反过来说,不依赖spring,专注测好一件事情。

UT理念应该是小而简单、保持独立、mock依赖都能正确工作。这应该是jmockit所追求的,所以强调脱离spring的正常工作。 但目前项目中,需要用ut做一部分业务自动化测试,因此可能junit + mockito更适合。

个人浅见,欢迎拍砖。

转载请注明原文地址: https://www.6miu.com/read-2628923.html

最新回复(0)