【问题标题】:How can I make Junit test, from my program (assertrue, assertEqual etc)?如何从我的程序(assertrue、assertEqual 等)中进行 Junit 测试?
【发布时间】:2022-01-02 15:29:04
【问题描述】:

这是问题:为市场创建程序。系统可以根据以下规则向消费者发送家庭卡并接受 0%(无折扣)、5% 或 10% 的折扣:

  1. 默认折扣选项是“无折扣”。
  2. 未注册用户没有折扣。未向未注册用户提供家庭卡。

如果注册用户在过去的食品购买上花费超过 1000 美元且购物次数少于 19 次,他们将获得 5% 的折扣。

  1. 如果注册用户在之前的杂货店购物时段中花费超过 1000 美元并且至少有 20 次杂货店购物时段,他们将获得 10% 的折扣。

  2. 只有消费超过 1000 美元或至少进行 20 次购物的注册用户才会收到一张家庭卡。

下面是我的代码

package Market;
import java.util.Scanner; 
public class Lab5
{
 public static void main(String[] args) 
 {
  
  int spent=0;
  int market_sessions=0; 
  Scanner scan =new Scanner(System.in); 
  System.out.printf("Amount spent by customer: "); 
  spent=Integer.parseInt(scan.nextLine());
  Scanner scan2 =new Scanner(System.in);
  System.out.printf("Marketsessions by the customer: ");
  market_sessions=Integer.parseInt(scan2.nextLine());
  
  int a = 0;
int type=userType(a);
  if(type==1) 
  {
   int discount=discounts(spent, market_sessions);
   
   System.out.println("Discount: "+discount);
   if(spent>1000 || market_sessions>=20)
    System.out.println("Family card is sent to the customer");
  }
  else 
  {
   System.out.println("Family cards and discounts are not given to unregistered users.");
  }
 }
 
 public static int discounts(int spent, int market_sessions)
 {
  int discount=0;
  if(spent>1000)
  {
   if(market_sessions<=19)
    discount=5;
   else
    discount=10;
  } 
  return discount;
  
 }

 public static int userType(int a)
 {
  System.out.println("Enter 1 or 2"); 
  System.out.println("1 = Registered User");
  System.out.println("2 = Unregistered User");
  Scanner scan3 =new Scanner(System.in);
  a=Integer.parseInt(scan3.nextLine());
 while(a<1 || a>2) {
     System.out.println("Enter 1 or 2"); 
      System.out.println("1 = Registered User");
      System.out.println("2 = Unregistered User");
      Scanner scan4 =new Scanner(System.in);
      a=Integer.parseInt(scan4.nextLine());
 }
 
  return a;
 
 }
}

我的程序运行良好。它满足问题中的条件。但我的问题是,无论我多么努力,我都无法运行 Junit 测试。因此,例如,我正在编写方法,但我不知道如何测试它。我尝试了很多,但我无法使您的 Junit 测试的逻辑。我的程序有问题吗? Junit 是否停止测试我的程序?因为我从键盘上得到数字,是这样吗?我不应该使用扫描仪吗?你能用我的程序写一个 Junit 测试吗?

【问题讨论】:

    标签: java unit-testing testing junit


    【解决方案1】:

    正如名称中的“单元”所暗示的那样,每个单元测试都应该专注于测试应用程序的一小部分(而不是整个应用程序)。

    实际平台输入和输出 (I/O) 不应成为单元测试的一部分。有多种方法可以模拟 I/O 类,因此您可以在测试中使用 Scanner 模拟,但即使这样也需要对当前代码进行一些重构才能成为可能。但我认为这不应该是你的目标。我认为您的目标应该是编写代码,以便在可能的情况下更容易进行单元测试而无需模拟平台代码。

    逻辑(领域逻辑、业务逻辑、应用程序中需要的任何逻辑)应限制在函数/方法中。理想情况下,只有这些函数的输入应该决定它们的输出,即理想情况下,您的函数应该没有副作用 (pure functions)。没有副作用的函数更容易测试。

    在您的情况下,方法 public static int discounts(int spent, int market_sessions) 包含您的一些应用程序逻辑,并且没有副作用,因此它是单元测试的理想候选者。

    单元测试将如下所示(使用 JUnit 5,如果您想使用 JUnit 4,它的 API 会有所不同)

    import Market.Lab5;
    import org.junit.jupiter.api.Test;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    public class Lab5Test {
    
        @Test
        public void registered_users_should_receive_a_discount_conditionally() {
            assertEquals(0, Lab5.discounts(Integer.MIN_VALUE, Integer.MIN_VALUE));
            assertEquals(0, Lab5.discounts(0, 0));
            assertEquals(0, Lab5.discounts(1000, 18));
            assertEquals(0, Lab5.discounts(1000, 19));
            assertEquals(0, Lab5.discounts(1000, 20));
    
            assertEquals(5, Lab5.discounts(1001, 18));
            // if we follow the rules strictly this discount should be 0,
            // but if we follow the common sense it should be 5
            // ask for clarification of the rules (if it is a typo in the rules or not)
            assertEquals(5, Lab5.discounts(1001, 19));
    
            assertEquals(10, Lab5.discounts(1001, 20));
            assertEquals(10, Lab5.discounts(Integer.MAX_VALUE, Integer.MAX_VALUE));
        }
    }
    

    if(spent&gt;1000 || market_sessions&gt;=20) 行中有更多逻辑。所以这一行可以重构为一个新的方法,这样就可以进行单元测试了。

    public static boolean supplyAfamilyCard(int spent, int market_sessions) {
        return spent>1000 || market_sessions>=20;
    }
    

    那么单元测试就可以了

    import Market.Lab5;
    import org.junit.jupiter.api.Test;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    public class Lab5Test {
        
        // ...
    
        @Test
        public void registered_users_should_receive_a_family_card_for_more_than_1000_spent() {
            assertFalse(Lab5.supplyAfamilyCard(Integer.MIN_VALUE, 19));
            assertFalse(Lab5.supplyAfamilyCard(0, 19));
            assertFalse(Lab5.supplyAfamilyCard(1000, 19));
        
            assertTrue(Lab5.supplyAfamilyCard(1001, 19));
            assertTrue(Lab5.supplyAfamilyCard(Integer.MAX_VALUE, 19));
        }
        
        @Test
        public void registered_users_should_receive_a_family_card_for_20_or_more_sessions() {
            assertFalse(Lab5.supplyAfamilyCard(true, 1000, Integer.MIN_VALUE));
            assertFalse(Lab5.supplyAfamilyCard(true, 1000, 0));
            assertFalse(Lab5.supplyAfamilyCard(true, 1000, 19));
        
            assertTrue(Lab5.supplyAfamilyCard(true, 1000, 20));
            assertTrue(Lab5.supplyAfamilyCard(true, 1000, Integer.MAX_VALUE));
        }
    }
    

    如果还没有,则必须将 org.junit.jupiter(或 JUnit 4)库依赖项添加到您的项目中,以便上述导入工作。如果您使用的是 Java IDE,它们中的每一个都有一种添加依赖项的方法。如果您正在使用构建系统并使用存储库(例如 Maven),您可以在构建脚本中添加 org.junit.jupiter(或 JUnit 4 等效项)作为依赖项。

    运行测试时,所有测试都通过(假设消费超过 1000 时 19 会话的折扣为 5,而不是规则建议的 0)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 2013-04-03
      相关资源
      最近更新 更多