当前位置: 首页 > 知识库问答 >
问题:

为什么我们不能使用Mockito为参数化构造函数创建spy

子车俊材
2023-03-14

我的代码中只有参数化构造函数,需要通过它进行注入。

我想刺探参数化构造函数以注入模拟对象作为junit的依赖项。

public RegDao(){
 //original object instantiation here
Notification ....
EntryService .....
}

public RegDao(Notification notification , EntryService entry) {
 // initialize here
}

we have something like below : 
RegDao dao = Mockito.spy(RegDao.class);

但我们有什么东西可以在构造函数中注入模拟对象并对其进行监视吗?。

共有2个答案

阎成天
2023-03-14

听起来您可能缺少依赖项注入解决方案。Mockito非常适合与DI一起注入Mock。例如,您可以使用CDI,将您的通知和入口服务成员注释为具有注入的成员,在测试中为这两个成员声明Mock,然后让Mockito将它们注入到您的RegDao中进行测试

这是我认为您正在尝试运行的测试的工作模型:

import static org.junit.Assert.assertEquals;

import javax.inject.Inject;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MockitoSpyInjection {
    static class Notification { }
    static class EntryService { }
    static class RegDao {
        @Inject
        Notification foo;

        @Inject
        EntryService  bar;

        public RegDao() {
        }

        public RegDao(Notification foo, EntryService bar) {
            this.foo = foo;
            this.bar = bar;
        }

        public Notification getFoo() {
            return foo;
        }

        public EntryService getBar() {
            return bar;
        }

    }


    @Mock
    Notification foo;

    @Mock
    EntryService bar;

    @Spy
    @InjectMocks
    RegDao dao;

    @Test
    public void test() {
        assertEquals(foo, dao.getFoo());
        assertEquals(bar, dao.getBar());
    }
}
江航
2023-03-14

您可以通过在junit中用参数化构造函数实例化主类,然后从中创建一个间谍来实现这一点。

让我们假设您的主类是A。其中,B和C是其依赖项

public class A {

    private B b;

    private C c;

    public A(B b,C c)
    {
        this.b=b;
        this.c=c;
    }

    void method() {
        System.out.println("A's method called");
        b.method();
        c.method();
        System.out.println(method2());

    }

    protected int method2() {
        return 10;
    }
}

然后您可以使用参数化类为此编写jUnit,如下所示

@RunWith(MockitoJUnitRunner.class)
public class ATest {

    A a;

    @Mock
    B b;

    @Mock
    C c;

    @Test
    public void test() {
        a=new A(b, c);
        A spyA=Mockito.spy(a);

        doReturn(20).when(spyA).method2();

        spyA.method();
    }
}

测试类输出

A's method called
20
  1. 这里BC是您使用参数化构造函数在类A中注入的模拟对象。
  2. 然后我们创建了一个名为spyA间谍
  3. 我们通过修改类A中受保护方法method 2的返回值来检查间谍是否真的在工作,如果spyA不是A的实际间谍
 类似资料:
  • 问题内容: 为什么我们必须在Servlets中重写init()方法,同时可以在构造函数中进行初始化,并让Web容器调用构造函数,同时在调用构造函数时将ServletConfig引用传递给Servlet? 当然,容器必须为此使用反射,但是容器仍然必须使用反射来调用简单的无参数构造函数 问题答案: 由于构造函数不能是接口的一部分,因此与常规方法不同,不能在Servlet API中“正式”指定构造函数。

  • 问题内容: 我想知道为什么我们不调用servlet构造函数而不是init方法来初始化配置参数。 谢谢 问题答案: 该线程应阐明差异。 引用以下更具启发性的帖子之一: init()方法通常用于执行servlet初始化-创建或加载servlet在处理其请求时使用的对象。为什么不使用构造函数呢?好吧,在JDK 1.0(最初为其编写servlet)中,动态加载的Java类(例如servlet)的构造函数不

  • 问题内容: 必须使用无参数构造函数(像Hibernate这样的工具会在此构造函数上使用反射来实例化对象)。 我得到了这个手挥手的答案,但是有人可以进一步解释吗?谢谢 问题答案: hibernate,并且通常通过反射创建对象的代码用于创建类的新实例。此方法需要一个公共的无参数构造函数才能实例化该对象。对于大多数用例,提供无参数构造函数不是问题。 有一些基于序列化的技巧可以解决没有no-arg构造函数

  • 我试图创建一个带有可选参数的模板函数,但我很难理解编译失败的原因。这是我的测试(设计)代码: 只有当我用这两个参数调用时,代码才会编译。如果我尝试只传递1个参数,编译将失败,出现以下错误: main.cpp:18:34:错误:调用'GetCountIf' std::cout<<“numelements=”< (我用的是C++14)

  • 我正试图用BlueJ完成一项为uni完成的任务,但我在第一个障碍上遇到了障碍。 在赋值中,我们得到了一个类,以及该类的构造函数、方法和参数的名称。我们不允许更改这些,因为赋值部分地由测试单元标记(或类似的东西)。 该类的一个构造函数如下所示 我已经(部分)完成了 我不明白的是为什么-为什么他们使用作为构造函数的参数?这样做有什么好处? (我想这样做肯定有好处(如果没有,功能就不会存在),但我不明白

  • 在C#、C和Java中,当你创建一个带参数的构造函数时,默认的无参数构造函数就消失了。我一直只是接受这个事实,但现在我开始想为什么。 这种行为的原因是什么?这仅仅是一个“安全度量/猜测”,说“如果你已经创建了自己的构造函数,你可能不希望这个隐含的函数四处游荡”?或者它有一个技术原因,使得编译器不可能在你自己创建构造函数后添加一个?