【问题标题】:Mock private wrapper/primitive/String field模拟私有包装器/原始/字符串字段
【发布时间】:2020-01-29 11:52:54
【问题描述】:

我的问题不是this 问题。 我想模拟像 Integer 和 String 这样的私有 wrapper 字段。 此外,这些字段位于抽象超类中。

public abstract class SuperSample
{
    private Integer var1;
    private String var2;

    private Service service;

    pubic boolean foo()
    {
          int a = service.doStuff(var1, var2);
          return subMethod(a);
    }

    protected abstract boolean subMethod(int var);

    public void setVar1(Integer var1)
    {
        this.va1 = var1;
    }

    public Integer getVar1()
    {
        return var1;
    }

    public void setVar2(String var2)
    {
        this.var2 = var2;
    }

    public String getVar2()
    {
        return var2;
    }

    public void setService(Service service)
    {
        this.service = service;
    }

    public String getService()
    {
        return service;
    }
}

public class Sample extends SuperSample
{
    protected boolean subMethod(int var)
    {
        return var%2==0?true:false;
    }
}

Spring.xml -

<bean id="superSample" class="SuperSample" abstract="true">
    <property name="var1" value="2" />
    <property name="var2" value="cool" />
</bean>

<bean id="sample" class="Sample" >
    <property name="service" ref="service" />
</bean>

在我的 junit 中,我无法模拟或监视 var1 或 var2。在监视/模拟 var1、var2 时出现错误:

org.mockito.exceptions.base.MockitoException:无法模拟/监视类 java.lang.Integer Mockito 无法模拟/监视以下内容: - 最后的课程 - 匿名类 - 原始类型

我想模拟这条线-

service.doStuff(var1, var2)

类似-

@UnitTest
public class SampleTest
{
    @Mock 
    private Service service;

    private Integer var1 = 2
    private String var2 = "cool";

    @InjectMocks
    private Sample sample;  

    @Test
    public void test()
    {
        MockitoAnnotations.initMocks(this); 
        Mockito.when(service.doStuff(var1, var2)).thenReturn(5);
    }
}

【问题讨论】:

  • 这似乎是一个 XY 问题。为什么你需要模拟Integer?让Integer.valueOf(1).intValue() 返回2 会给您的测试带来什么好处?为什么不能换一种方式解决?
  • 你想模拟 service.doStuff(var1, var2); 还是什么?
  • 如果你想模拟service.doStuff,你需要模拟Service并给你的Sample实例模拟Service而不是实际的Service
  • @FarrukhChishti 转换为使用构造函数注入,然后将mock传递给构造函数就很简单了。
  • @FarrukhChishti Spring 至少在过去 12 年里一直支持构造函数注入。

标签: java unit-testing junit mockito


【解决方案1】:

您可以简单地自己注入值,然后删除 @InjectMocks 注释。这最好在带有 @Before 注释的 setup 方法中完成,以便在每次测试时执行。

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
    sample = new Sample();
    sample.setVar1(1234);
    sample.setVar2("5678");
    sample.setService(service);
}

【讨论】:

  • 关于在foo()方法上应用调试
  • @FarrukhChishti 你用过我的setup() 方法吗?是否使用@Before(或其他测试框架中的等效项)进行注释,以便在每次测试之前运行?
  • 是的……我也更新了我的问题……这些变量实际上是在一个抽象的超类中……你能再看看吗……谢谢
【解决方案2】:

根据当前显示的示例,可以通过 set 成员注入模拟

@UnitTest
public class SampleTest {
    @Mock 
    private Service service;

    private Integer var1 = 2
    private String var2 = "cool";

    @Test
    public void test() {
        //Arrange
        MockitoAnnotations.initMocks(this);

        Sample sample = new Sample();
        sample.setService(service);
        sample.setVar1(var1);
        sample.setVar2(var2);          

        Mockito.when(service.doStuff(var1, var2)).thenReturn(5);

        //Act
        boolean actual = sample.foo();

        //Assert

        //...
    }
}

理想情况下,更可靠的设计方法是重构主题类以通过构造函数注入使用显式依赖原则

public class Sample extends SuperSample {

    public Sample(Service service) {
        super.setService(service);
    }

    protected boolean subMethod(int var) {
        return var%2==0?true:false;
    }
}

允许注入任何显式依赖项

@UnitTest
public class SampleTest {
    @Mock 
    private Service service;

    private Integer var1 = 2
    private String var2 = "cool";

    @InjectMocks
    private Sample sample;  

    @Test
    public void test() {
        //Arrange
        MockitoAnnotations.initMocks(this); 

        sample.setVar1(var1);
        sample.setVar2(var2);  

        Mockito.when(service.doStuff(var1, var2)).thenReturn(5);

        //Act
        boolean actual = sample.foo();

        //Assert

        //... 
    }
}

【讨论】:

  • 但我正在从 spring.xml 注入 bean 和变量。为什么要重写构造函数?
【解决方案3】:

你去吧,我们创建了一个 JUnit 扩展来解决这个精确的问题。

https://github.com/exabrial/mockito-object-injection

【讨论】:

  • 非常感谢!!!!老实说,这太棒了。一年中的任何一天都可以随时向我要肾。
猜你喜欢
  • 1970-01-01
  • 2012-06-28
  • 2017-12-04
  • 2010-10-09
  • 2012-12-06
  • 1970-01-01
  • 2018-09-26
  • 2013-07-14
  • 1970-01-01
相关资源
最近更新 更多