Java JUnit—在测试方法中使用的模拟类

Java JUnit—在测试方法中使用的模拟类,java,junit,Java,Junit,即两类: 现在我想为B类编写一个测试,但我想为该测试模拟a类。问题是:怎么做 (这段代码只是我问题的一个简单版本,请不要在意返回5或smth)可能有一些棘手的方法,但简而言之,您编写B的方式不支持模拟。尝试将A注入B,而不是在B中实例化A 考虑将其更改为 class B { private A a; public void setA(A a) { this.a=a; } public int getValue(){ return a.getValue(); }

两类:

现在我想为B类编写一个测试,但我想为该测试模拟a类。问题是:怎么做


(这段代码只是我问题的一个简单版本,请不要在意返回5或smth)

可能有一些棘手的方法,但简而言之,您编写
B
的方式不支持模拟。尝试将A注入B,而不是在B中实例化A

考虑将其更改为

class B {
  private A a;
  public void setA(A a) {
    this.a=a;
  }
  public int getValue(){
    return a.getValue();
  }
}
您甚至可以通过
privatea=newa()
初始化
a
,但提供setter允许您为测试注入模拟


编辑:如果重写B以使其对单元测试友好有困难,您仍然可以使用模拟框架来执行字节码操作,如Powermock。下面是一个实现您的目标的示例:


也许有一些棘手的方法可以做到这一点,但简而言之,您编写
B
的方式不利于模拟。尝试将A注入B,而不是在B中实例化A

考虑将其更改为

class B {
  private A a;
  public void setA(A a) {
    this.a=a;
  }
  public int getValue(){
    return a.getValue();
  }
}
您甚至可以通过
privatea=newa()
初始化
a
,但提供setter允许您为测试注入模拟


编辑:如果重写B以使其对单元测试友好有困难,您仍然可以使用模拟框架来执行字节码操作,如Powermock。下面是一个实现您的目标的示例:


模拟类用于获取测试其他类功能所需的数据。在本例中,类A不使用mock类,因为它只返回5。但如果是类A中的业务逻辑,则应该使用模拟类。创建一个新类,并在原始类中添加相同的方法名,不做任何逻辑,只需从中返回一些值

模拟类用于获取测试其他类功能所需的数据。在本例中,由于模拟类只返回5,因此不会对类使用模拟类。但如果是类A中的业务逻辑,则应该使用模拟类。创建一个新类,并在原始类中添加相同的方法名,不做任何逻辑,只需从中返回一些值

模拟可以使用
实例变量
完成,并为相同的变量设置一个
设置器

下面的两个链接可能会帮助您了解您正在尝试做的上述事情


模拟可以使用
实例变量
完成,并为相同的变量设置一个
设置器

下面的两个链接可能会帮助您了解您正在尝试做的上述事情


如果设置器仅用于测试,则应进行包装保护。然后你几乎可以肯定,没有人会更改A实例。好吧,但我不想更改代码。。。我想为它编写测试:)顺便说一下,这段代码只是对我的problem@agad:是的,如果它只是为了测试,我们应该保护它。然而,我相信如果类被正确重写,注入setter应该是公共的:)@Mart.ini:我相信编写单元测试友好的代码总是更好的。然而,如果你真的坚持要在你的帖子的原始案例中进行模拟,你可以看看Powermock,因为它实际上改变了
a
的类,所以应该可以进行这种模拟(很抱歉,我以前没有机会使用Powermock,因此不能给你一个例子)@Mart.ini发现您的Powermock页面与您的案例非常接近,请参阅edit如果setter仅用于测试,则它应受到包保护。然后你几乎可以肯定,没有人会更改A实例。好吧,但我不想更改代码。。。我想为它编写测试:)顺便说一下,这段代码只是对我的problem@agad:是的,如果它只是为了测试,我们应该保护它。然而,我相信如果类被正确重写,注入setter应该是公共的:)@Mart.ini:我相信编写单元测试友好的代码总是更好的。然而,如果你真的坚持要在你的帖子的原始案例中进行模拟,你可以看看Powermock,因为它实际上改变了
a
的类,所以应该可以进行这种模拟(很抱歉,我以前没有机会使用Powermock,因此不能给你一个例子)@Mart.ini发现您的Powermock页面与您的案例非常接近,请参见编辑