JUnit 註解@RunWith的工作原理
In order to introduce the usage of this annotation in JUnit, I use an example to demonstrate.
I have a very simple price calculator:
public class PriceCalculator {
private int quantity;
private double unitPrice;
private double discount;
public PriceCalculator(int quantity, double price, double discount){
this.quantity = quantity;
this.unitPrice = price;
this.discount = discount;
}
public double getPrice(){
return this.quantity * this.unitPrice * ( this.discount / 100 );
}}
Test class for this calculator:
import static org.junit.Assert.assertEquals;import org.junit.Test;public class RunWithOneTestCase {
private final static int QUANTITY1 = 5;
private final static double PRICE1 = 10;
private final static double DISCOUNT1 = 90;
private final static double EXPECTED1 = QUANTITY1 * PRICE1 * ( DISCOUNT1 / 100 );
private final static int QUANTITY2 = 4;
private final static double PRICE2 = 5;
private final static double DISCOUNT2 = 80;
private final static double EXPECTED2 = QUANTITY2 * PRICE2 * ( DISCOUNT2 / 100 );
@Test
public void testPriceCalculation(){
PriceCalculator priceCalculator = new PriceCalculator(QUANTITY1, PRICE1, DISCOUNT1);
assertEquals("price calculated for test data1",
EXPECTED1, priceCalculator.getPrice(), 0);
PriceCalculator priceCalculator2 = new PriceCalculator(QUANTITY2, PRICE2, DISCOUNT2);
assertEquals("price calculated for test data2",
EXPECTED2, priceCalculator2.getPrice(), 0);
}}
The disadvantage of this solution: here I have two sets of test data, so duplicate static attribute QUANTITY2, PRICE2, DISCOUNT2 and EXPECTED2 are introduced, which is a violation of DRY – Don’t Repeat Yourself.
A better solution
import static org.junit.Assert.assertEquals;import java.util.Arrays;import java.util.Collection;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.Parameterized;import org.junit.runners.Parameterized.Parameters;@RunWith(Parameterized.class)public class RunWithTwoTestCase {
private int quantity;
private double price;
private double discount;
private double expected;
private PriceCalculator priceCalculator;
public RunWithTwoTestCase(int qty, double price, double discount, double expected){
this.quantity = qty;
this.price = price;
this.discount = discount;
this.expected = expected;
}
@Parameters(name = "{index}: (Quantity {0} * Price {1}) * (Discount{2}/100) = {3}")
public static Collection<Object[]> generateData()
{
return Arrays.asList(new Object[][] {
{ 5, 10, 90, 45 },
{ 4, 5, 80, 16 } });
}
@Before
public void setUp() throws Exception {
this.priceCalculator = new PriceCalculator(this.quantity, this.price, this.discount);
}
@Test
public void testPrice(){
assertEquals("price calculated for test data", this.expected,
this.priceCalculator.getPrice(), 0);
}}
Briefly introduction
The advantage of this solution is, the test data is in fact somehow separated from test class itself. In case you need more test data, you can simply append array in method generateData() without any duplicate static attributes.
Another benefit is, the test data injected with @Parameters are also available in JUnit result view, which is easier for tester to analyze result. Just compare the normal test case and the solution where @Parameters is used:
In the runtime, (1) the annotation “@org.junit.runners.Parameterized$Parameters(name={index}: (Quantity {0} * Price {1}) * (Discount{2}/100) = {3})” I write in method generateData is extracted by framework:
After that call allParameters method to retrieve test data written in test code. (2) In allParameters method, my prepared test data is passed to JUnit framework via reflective call:
(3) then my test case class is instantiated by reflection, the first set of test data is passed into constructor. After that the method annotated with @Before and @Test are executed sequentially. And then, @Before and @Test will be executed once again for the second set of test data. This could be observed by id displayed in debugger.
要獲取更多Jerry的原創文章,請關注公眾號"汪子熙":
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2722715/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JUnit 註解@Category的工作原理Go
- JUnit 註解@SuiteClasses的工作原理UI
- JUnit 註解@Rule的工作原理
- Java JUnit框架裡@Category註解的工作原理Java框架Go
- Angular @Injectable 註解的工作原理淺析Angular
- Spring框架裡註解@Autowired的工作原理Spring框架
- JUnit5註解學習指引
- SAP Fiori @OData.publish 註解的工作原理解析
- 暑期自學 Day 07 | Junit,反射,註解(一)反射
- 暑期自學 Day 08 | Junit,反射,註解(二)反射
- 使用Java JUnit框架裡的@Rule註解的用法舉例Java框架
- Spring系列之新註解配置+Spring整合junit+註解注入Spring
- Transaction註解原理
- Angular @Inject 註解的實際應用例子和工作原理淺析Angular
- SAP Fiori 註解 @ObjectModel.readOnly工作原理解析Object
- 使用Java JUnit框架裡的@SuiteClasses註解管理測試用例Java框架UI
- @LoadBalanced註解原理
- JAVA 註解的基本原理Java
- Java註解與原理分析Java
- 深入瞭解Azure 機器學習的工作原理機器學習
- Nginx的工作原理和配置詳解Nginx
- spring JUnit 基本原理Spring
- SpringMVC工作原理詳解SpringMVC
- JUnit5學習之五:標籤(Tag)和自定義註解
- 代理伺服器的工作原理詳解伺服器
- SAP Fiori程式設計模型規範裡註解 - @OData.publish工作原理解析程式設計模型
- Struts2工作原理(圖解)圖解
- 交換機的作用、功能和工作原理詳解
- 解讀MySQL的InnoDB引擎日誌工作原理MySql
- Mirror 的工作原理
- Spark的工作原理Spark
- View的工作原理View
- HashMap的工作原理HashMap
- DHCP的工作原理
- tcmalloc的工作原理
- undo的工作原理
- OAuth的工作原理OAuth
- 從 java 註解分析 ButterKnife 工作流程Java