简体   繁体   English

如何模拟带有私有字段的课程?

[英]How do I mock a class with private fields?

I'm trying to test a singleton class with Mockito, something like this: 我正在尝试使用Mockito测试单例类,如下所示:

  public class Single {
     private ID id;
     private Single(){}  //private constructor 
     public static Single getSingle(){ // ***code to get instance*** }

     // method I want to test
     public String getName(){ 
        String name = id.getRawName(); // need field id here
        ** additional operations on name ** // code need to be tested
        return name;
     }

  }

I tried to mock this class and set field "id" with reflection, like this: 我尝试模拟此类,并使用反射设置字段“ id”,如下所示:

Single sg = Mockito.mock(Sincle.class);
Field myID = sg.getClass().getDeclaredField("id"); // fails here
myID.setAccessible(true);
myID.set(sg, <ID instance>);

However it fails at getDeclaredField() method, with exception 但是,它在getDeclaredField()方法中失败,例外

java.lang.NoSuchFieldException: id java.lang.NoSuchFieldException:id

I guess it's because id field is null in instance sg. 我猜这是因为实例sg中的id字段为null

So I'm wondering if there's anything I can do to test this method without modify the original class? 所以我想知道是否可以在不修改原始类的情况下测试此方法?

A mock is not a real object. 模拟不是真实的对象。 You can't set a declared field of a mock because it doesn't exist 1 ! 您不能设置模拟的声明字段,因为它不存在1

When you are writing tests, you generally want to mock all the classes that are not : 在编写测试时,通常希望模拟所有不是的类:

  • The System Under Test (in this case, the Single ) class 被测系统 (在本例中为Single )类
  • Data Structures (like List ) and other POJO s. 数据结构(如List )和其他POJO

Therefore, the thing you really want to be mocking is ExternalCall , which you don't really explain how it works in your question. 因此,您真正要嘲笑的东西是ExternalCall ,您并没有真正解释它在您的问题中的工作方式。 However, if it's a static method, you need to use PowerMock . 但是,如果这是静态方法,则需要使用PowerMock See: Mocking static methods with Mockito 请参阅: 用Mockito模拟静态方法

Note that your error is NoSuchFieldException , because you don't actually have a real instance. 请注意,您的错误是NoSuchFieldException ,因为您实际上没有真实的实例。 It's not because: 不是因为:

I guess it's because id field is null in instance sg. 我猜这是因为实例sg中的id字段为null

It's because the field actually doesn't exist 1 in the mockito generated subclass , not because it's null . 这是因为该字段在模仿生成的子类中 实际上不存在1 ,不是因为它为null

1: It does exist in mock's superclass (in this case, Single ), but its value is captured by the mocking behavior and is ignored unless you use it as a partial mock. 1:它确实存在于模拟的超类(在本例中为Single )中,但是其值被模拟行为捕获,除非您将其用作部分模拟,否则它将被忽略。 However, this is a technical detail and not relevant to the proper using of Mockito. 但是,这是技术细节,与Mockito的正确使用无关。

...anything I can do to test this method without modify the original class? ...在不修改原始类的情况下,我能做些什么来测试此方法?

Yes, there is. 就在这里。 Use Mockito for its bread-and-butter purposes: 将Mockito用作面包和黄油:

when(sg.getId()).thenReturn("123")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM