【问题标题】:How to mock a method from a class that it is from jar (JAVA)如何模拟来自jar(JAVA)的类中的方法
【发布时间】:2018-01-29 21:43:34
【问题描述】:

我无法解决上周一直困扰我的问题。

可以模拟一个在 jar 中的类,所以我不调用真正的方法。

示例:

3 个类(Person 类、PersonTest 类、PersonExternalJar 类)

public class Person{

     private PersonalExternalJar pej;

     public void methodA(){
          *do some stuff*
           pej = new PersonalExternalJar();
           ArrayList people = pej.doSomething(AnyString,AnyString,AnyObject);
           *do some stuff*
           People2 p = new People2(); //  This class it is somewhere in my project lets say
           String SomePeople = p.doSomeStuff();

     }
}


@RunWith(MockitoJUnitRunner.class)
public class PersonTest{
     @Mock private People2 p;
     @Mock private PersonExtenarlJar pej; // I get an error like I can't find this class or some internal thing of this class.

     @InjectMocks private Person  pr;

     @Test
     public void personTest(){
          *do some stuff*
           pr = new Personal();
           //try both declare the class and not declaring the class
           //when I do the next 
           Mockito.doReturn("anything").when(p).doSomeStuff(); // WORKS
           Mockito.doReturn(AnyArray).when(pej).doSomething(AnyString,AnyString,AnyObject) // CAN'T DO THIS 
           //Doesn't work
           //Alternatively I tried to take off the annotation mock and do the following.   
            PersonalExternalJar pej = Mockito.mock(PersonalExternalJar.class) 
            //Still doesn't work.
     }
}

据我了解,单元测试是在不调用外部方法的情况下隔离类并尝试其行为(这就是我使用 mockito 的原因)。

Mockito 核心版本 1.10.19 六月 4.12。

我希望有人能给我一个解决方案,或者让我看到另一个观点,或者让我明白我可能对概念感到困惑。

【问题讨论】:

  • 当您将代码与您无法控制的第 3 方代码紧密耦合时,就会发生这种情况。将外部依赖封装在您控制的抽象后面,并将它们显式注入到您的依赖类中。使模拟和维护您的代码更加灵活。
  • @dherik 是的,这是一个我可以修改的类。
  • @nkosi 这是我无法控制的第 3 方代码,但它使我们能够访问数据库。我需要它来耦合我的代码,因为它是强制性的。我以某种方式找到了一种使用和伪造电话的方法。不过谢谢。
  • 我认为 SpringJUnit4ClassRunner 不支持 Mockito 的 Mock 和 InjectMocks 注解。要启用此功能,您需要 RunWith(MockitoJUnitRunner.class)。以及赋值“pej = new PersonalExternalJar();”似乎没有意义。它将覆盖注入的模拟。您可以在声明中(或在构造函数中)对其进行初始化。
  • @StefanGroßmann 您好,感谢您的回答。抱歉,我想写 MockitoJunitRunner.class。我的错。我不明白的是你所说的 pej = PersonalExternalJar() 似乎没有意义。 Person 类需要在某个地方初始化该类吗?为了使用他们的方法。 Person 它是我正在测试的类,里面的其他类,我需要模拟它们。

标签: java unit-testing mockito junit4


【解决方案1】:

您需要在 Person 类中使用 PersonalExternalJar 公开依赖项来模拟它。一种方法是使用构造函数。

所以将Person 类重构为这样:

public class Person {

     private final PersonalExternalJar pej;

     public Person (PersonalExternalJar pej) {
         this.pej = pej;
     }

     public void methodA(){
          *do some stuff*
           ArrayList people = pej.doSomething(AnyString,AnyString,AnyObject);
           *do some stuff*
           People2 p = new People2(); //  This class it is somewhere in my project lets say
           String SomePeople = p.doSomeStuff();

     }
}

在应用程序代码中:

new Person(new PersonalExternalJar());

在你的测试中:

PersonalExternalJar pejMocked = mock(PersonalExternalJar.class);
new Person(pejMocked);

您还可以选择使用set 方法而不是constructor

public class Person {
     private PersonalExternalJar pej;

     setPersonalExternalJar(PersonalExternalJar pej) {
         this.pej = pej;
     }
}

【讨论】:

  • 还应该从设计的角度添加,如果PersonalExternalJar 除了一个方法之外没有其他角色,那么它应该显式地注入方法而不是构造函数。除此之外,您所拥有的是准确的。
  • 我已经试过了。亲自制作构造函数并将 PersonalExternalJar 作为参数传递。但是给我带来的问题是对该类使用@mock 注释,或者使用 Mockito.mock(PersonalExternalJar.class)。有一个错误,比如我找不到类。
  • @Nkosi,你能详细说明一下吗?我总是使用构造函数,因为这样可以更好地显示类的所有依赖项,并且您不会因为未设置某些依赖项而冒着拥有一些 NPE 的风险。
  • 我同时使用了构造函数或设置选项。我是新手,但我做了我的研究。谢谢!
  • @mariosalirrosas,什么错误?也许您的项目中有一些范围问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2016-07-17
  • 1970-01-01
  • 2018-01-09
  • 1970-01-01
  • 2018-07-17
相关资源
最近更新 更多