【问题标题】:Mockito not returning expected valueMockito 没有返回预期值
【发布时间】:2018-05-16 14:24:01
【问题描述】:

我正在使用 JUnitMockito 库来测试我的应用程序。问题是,当我在代码下方执行时,该值在运行时未返回空列表,并且测试失败。理想情况下,当getEmployee() 被执行时,它应该返回空列表

public class Check_Test extends TestCase
{
    public void testMyCheck()
    {
        Check checkObj = new Check();
        EmployeeFactory employeeFactoryMock = Mockito.mock(EmployeeFactory.class);
        Mockito.doReturn(Collections.EMPTY_LIST).when(employeeFactoryMock).getEmployee();
        String str = checkObj.myCheck();
        assertEquals("", str);
    }
}

我尽我所知尝试了所有可能性,但我无法通过这个测试用例。

下面的Check 类具有myCheck() 方法,我需要测试是否为空...

public class Check
{
    public String myCheck()
    {
        List<Employee> employee = EmployeeFactory.getInstance().getEmployee();
        if (employee.isEmpty())
        {
            return ""; //Line No. 8 returning empty but, control is not coming here
        }
        else
        {
            return "NotEmpty"; // The control is always coming here ????
        }
    }
}

我热切期待支持。任何人都可以帮助我,如何通过这个测试用例???。如何通过 Mockito 使第 8 行的控件通过测试用例???

请假设,下面两个类没有真正的代码,我们只有二进制文件作为 JAR 文件,我们不能修改下面的代码......我附上这个以便我们理解......

public class EmployeeFactory
{

    private EmployeeFactory()
    {

    }

    public static EmployeeFactory getInstance()
    {
        return EmployeeFactoryHelper.INSTANCE;

    }

    private static class EmployeeFactoryHelper
    {
        public static final EmployeeFactory INSTANCE = new EmployeeFactory();
    }

    private static List<Employee> employees = null;

    static
    {
        employees = Arrays.asList(
                                  new Employee("Manish", "Kumar", true, 60),
                                  new Employee("Siva", "Attla", true, 42),
                                  new Employee("Anand", "Manivel", false, 51),
                                  new Employee("Madhavi", "Govind", true, 45),
                                  new Employee("Janani", "Chidambaram", true, 45),
                                  new Employee("Mannu", "Krishna", false, 39),
                                  new Employee("Karthika", "Hosamane", false, 39)
                          );
    }

    public List<Employee> getEmployee()
    {
        return employees;

    }

}


public class Employee
{

    private String firstName;
    private String lastName;
    private boolean workStatus;
    private int age;

    public Employee(String firstName, String lastName, boolean workStatus, int age)
    {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.workStatus = workStatus;
        this.age = age;
    }

    public String getFirstName()
    {
        return firstName;
    }

    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    public String getLastName()
    {
        return lastName;
    }

    public void setLastName(String lastName)
    {
        this.lastName = lastName;
    }

    public boolean isWorkStatus()
    {
        return workStatus;
    }

    public void setWorkStatus(boolean workStatus)
    {
        this.workStatus = workStatus;
    }

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }

    @Override
    public String toString()
    {
        return "Employee [firstName=" + firstName + ", lastName=" + lastName + ", workStatus=" + workStatus + ", age=" + age + "]";
    }

}

【问题讨论】:

  • 你能试试这个语法吗? when(employeeFactoryMock.getEmployee()).thenReturn(Collections.&lt;Employee&gt;emptyList());
  • 没错。不要使用 Collections.EMPTY_MAP,而是使用 emptyMap() 方法。对于较新的 Java,您也不需要 &lt;Employee&gt; 部分。
  • @RonNabuurs :是的,我也试过了,还不行。
  • 我用更多信息更新了我的答案。但请注意,您的代码还有很多事情......不好。您使用的某些名称毫无意义(例如 class Check 、 myCheck ... 不会告诉您有关检查的内容)甚至具有误导性(例如使用 employee 表示单数来保存 list雇员)。拥有那个静态助手类也很奇怪,实际上:那里的整个工厂设计只是“错误”。
  • 这不是原始代码,我创建了场景供开发人员理解,以便我尽快得到解决方案。你可以忽略这里的类和方法命名转换。

标签: java junit mockito


【解决方案1】:

“通常”的事情:你不明白自己在做什么。

含义:仅仅“创建”一个模拟对象是不够的。您必须以某种方式确保您正在测试的代码使用了相应的 mocked 对象,例如使用@InjectMocks 注释。

本质上,你真正的问题是你开始使用 Mockito 却没有理解它。低效的策略。相反,您应该从自上而下阅读一个好的 Mockito/Junit 教程(如 this one)开始。 了解什么是模拟,以及你应该如何使用它们。以及如何确保您的被测代码使用模拟对象。

这里的问题是您创建了不必要的难以测试的代码。鉴于您的 当前 设计,您必须使用 PowerMock(ito) 或 JMockit - 因为您必须“拦截”此调用

public static final EmployeeFactory INSTANCE = new EmployeeFactory();

您的问题是您必须控制 INSTANCE 对象。由于您没有对该对象的访问权,因此您必须拦截对 new() 的调用,并且只有 PowerMock(ito) 或 JMockit 允许您这样做.

所以,真正的答案是像这样改变你的设计:

public class Check { 
   private final EmployeeFactory factory;
   public Check() { this(EmployeeFactory.getInstance()); } 

   Check(EmployeeFactory factory) { this.factory = factory }

  public String myCheck() {
    List<Employee> employee = factory.getEmployee();
    ...

现在,您可以使用接受参数的构造函数轻松注入 mocked 工厂对象,该对象返回您需要返回的内容。

【讨论】:

  • 您好,请问您能提供以上解决方案吗?如何测试 myCheck() 的空列表方法??
【解决方案2】:

不要调用静态工厂方法,而是注入工厂(可能在构造函数中)并在类中使用它。这样你就可以解耦类,你将能够在测试阶段注入一个模拟而不是真正的实现。 小例子:

class EmployeeFactory{
  public Employee getEmployee(){...}
}

class Check{
  private EmployeeFactory factory;
  public Check(EmployeeFactory factory){ this.factory = factory;

  public String myCheck()
  {
    List<Employee> employee = factory.getEmployee();
}

在模拟中:

public class Check_Test extends TestCase
{
    public void testMyCheck()
    {
        EmployeeFactory employeeFactoryMock = Mockito.mock(EmployeeFactory.class);
        Check checkObj = new Check(employeeFactoryMock);
        Mockito.doReturn(Collections.EMPTY_LIST).when(employeeFactoryMock).getEmployee();
        String str = checkObj.myCheck();
        assertEquals("", str);
    }
}

【讨论】:

  • 非常感谢您的支持。它工作正常。
【解决方案3】:

模拟实例根本没有被使用。您的测试仍在使用在 EmployeeFactory 类中创建的单例。

为了纠正这种情况,您需要允许注入单例实例,以便它可以在测试期间使用模拟,并在发布版本中使用实际实例。

【讨论】:

    猜你喜欢
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    相关资源
    最近更新 更多