【问题标题】:JUnit - Variables inside @Before not foundJUnit - @Before 中的变量未找到
【发布时间】:2018-06-19 17:57:13
【问题描述】:

我正在尝试执行以下代码。我的 IDE 告诉我

USER_ROLE_EMPLOYEE 无法解析为变量

这是我的代码:

public class TestUserHelper {

    @Before
    public void setUp() throws Exception {
        String USER_ROLE_EMPLOYEE="Service Desk";
        String USER_ROLE_MANAGER="Store Manager";
    }

    @Test
    public void testIsUserRoleValidEmployee() {
        Assert.assertTrue(UserValidator.validateSupervisor(USER_ROLE_EMPLOYEE));
    }

    @Test
    public void testIsUserRoleValidSupervisor() {
        Assert.assertTrue(UserValidator.validateSupervisor(USER_ROLE_MANAGER));
    }
}

我收到一条错误消息,提示 USER_ROLE_EMPLOYEE, USER_ROLE_MANAGER 无法解析为变量。

我做错了什么?

【问题讨论】:

  • 变量是setUp()方法的local变量。因此它们仅在该方法中可见。在询问错误时:总是阅读并发布准确且完整的错误消息
  • 谢谢JB。你知道修复是什么吗?无论如何我仍然可以保留@Before并删除错误吗?
  • 变量需要是instance变量。 stackoverflow.com/questions/16686488/…。或者,因为它们实际上是常量,所以是静态最终变量。

标签: java junit local-variables


【解决方案1】:

Java 有不同类型的变量:

  • 局部变量。这些是在方法内部声明的,并且只能从同一方法内部访问。我们说这些变量具有局部范围。您的 USER_ROLE_EMPLOYEEUSER_ROLE_MANAGER 变量是局部变量。因此,无法从声明它们的方法以外的方法访问它们。
  • 实例变量。它们分别存在于类的每个实例中,并且可以从类中的任何 非静态 方法访问。与局部变量相反,它们也可以从您的类外部访问;但是始终需要该类的实例。您可以像声明局部变量一样声明它们,只是将声明放在任何方法的外部(直接在您的类中)。他们应该在顶部。您应该为它们添加一个访问修饰符(如private),阅读更多关于here的信息。
  • 还有类变量static变量)。与实例变量不同,它们只存在一次,并且可以从类中的任何方法访问(甚至是static 方法)。在与实例变量相同的位置声明类变量,但使用 static 关键字。与实例变量一样,这些变量可以从类外部访问,具体取决于您声明的访问修饰符。与实例变量不同,它们不需要您的类的实例。

因此,在您的代码中,您可以:

  1. 使用实例变量而不是局部变量:

    public class TestUserHelper {
    
        private String USER_ROLE_EMPLOYEE, USER_ROLE_MANAGER;
    
        @Before
        public void setUp() throws Exception {
            USER_ROLE_EMPLOYEE = "Service Desk";
            USER_ROLE_MANAGER = "Store Manager";
        }
    
        @Test
        public void testIsUserRoleValidEmployee() {
            Assert.assertTrue(UserValidator.validateSupervisor(USER_ROLE_EMPLOYEE));
        }
    
        @Test
        public void testIsUserRoleValidSupervisor() {
            Assert.assertTrue(UserValidator.validateSupervisor(USER_ROLE_MANAGER));
        }
    }
    
  2. 或者,我推荐第二种方法,因为您的变量实际上是常量:将它们声明为static(类变量)和final(常量)。您将无法再在 setUp() 中初始化它们,但鉴于它们是恒定的,这不是问题:

    public class TestUserHelper {
    
        private static final String USER_ROLE_EMPLOYEE = "Service Desk";
        private static final String USER_ROLE_MANAGER = "Store Manager";
    
        @Test
        public void testIsUserRoleValidEmployee() {
            Assert.assertTrue(UserValidator.validateSupervisor(USER_ROLE_EMPLOYEE));
        }
    
        @Test
        public void testIsUserRoleValidSupervisor() {
            Assert.assertTrue(UserValidator.validateSupervisor(USER_ROLE_MANAGER));
        }
    }
    

【讨论】:

  • 你为什么建议public而不是private
  • @user7294900 我的错。你是对的——他们没有理由不能成为private。我已经编辑了。
【解决方案2】:

Before 是一个设置方法,当前变量仅在方法范围内是局部的,将其作为常量移动到类中,正如@JB Nizet 提到的那样

    private final static String USER_ROLE_EMPLOYEE="Service Desk";

【讨论】:

    【解决方案3】:

    @O.OBalance 的回答非常好,我要补充一点,局部变量可以变得更加局部!

    他简要介绍了作用域,我想补充一个更广泛的作用域定义:大括号 ({}) 之间的任何代码都是 作用域。局部变量是作用域的局部变量。这意味着您可以让变量仅可用于方法的一部分。

    一个常见的例子是循环:

    public int test(){
      int a = 1;
      while(a < 10){
        int b = 2;
        a += b;
      }
      if (b = null) {
        System.out.println("See ?");
      }
      {
        str b = "this is a scope";
      }
      if (b = null) {
        System.out.println("And see this too ?");
      }
      return a;
    }
    

    【讨论】:

    • 虽然这个答案澄清了范围的主题,但它并没有具体回答 OP 提出的问题,可能应该作为评论发布。
    • 这是我的意图,但我需要至少 50 的声誉才能发表评论,我还没有:/ 如果你愿意,可以将我的答案作为评论,我会删除我的答案。
    猜你喜欢
    • 1970-01-01
    • 2017-08-28
    • 2013-12-02
    • 2020-03-12
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多