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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45514907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 08:43:53  来源:igfitidea点击:

why cannot we create spy for Parameterized Constructor using Mockito

javamockitojunit4

提问by Pradeep

I have only parameterized constructor in my code and i need to inject through it.

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

I want to spy parameterized constructor to inject mock object as dependency for my junit.

我想监视参数化构造函数来注入模拟对象作为我的 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);

But do we have something that i can inject mocked object in the Constructor and spy it?.

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

回答by Dhawal Kapil

You can do that by instantiating your main class with parametrized constructor in your junit and then creating a spy from it.

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

Let's suppose your main class is A. Where Band Care its dependencies

假设您的主要课程是A. 在哪里BC在它的依赖

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;
    }
}

Then you can write junit for this using your parametrized class as below

然后你可以使用你的参数化类为此编写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();
    }
}

Output of test class

测试类的输出

A's method called
20
  1. Here Band Care mocked object that you injected in your class Ausing parametrized constructor.
  2. Then we created a spyof Acalled spyA.
  3. We checked if spyis really working by modifying the return value of a protected method method2in class Awhich could not have been possible if spyAwas not an actual spyof A.
  1. 这里BC是您A使用参数化构造函数注入到类中的模拟对象。
  2. 然后,我们创建了一个spyAspyA
  3. 我们检查,如果spy真的通过修改保护方法的返回值工作method2在课堂上A可能不会有可能的,如果spyA是不实际spyA

回答by Isaac Truett

It sounds like you might be missing a dependency injection solution. Mockito is great for working with your DI to inject mocks. For example, you can use CDI, annotation your Notificationand EntryServicemembers with @Inject, declare @Mocks for both in your test, and then let Mockito inject those into your RegDaofor testing.

听起来您可能缺少依赖注入解决方案。Mockito 非常适合与您的 DI 一起注入模拟。例如,您可以使用 CDI,使用 注释您NotificationEntryService成员@Inject@Mock在您的测试中为两者声明s,然后让 Mockito 将它们注入您RegDao的测试中。

Here's a working mockup of the test I think you're trying to run:

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

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());
    }
}