Why can't we create a spy for a Parameterized Constructor using Mockito

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

I want the spy parameterized constructor to inject the mock object as a dependency for my 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 add to the constructor project and fake it?

+3


source to share


2 answers


You can do this by creating your main class with a parameterized constructor in your junit and then creating a spy from it.

Let's assume your main class A

. Where B

and C

are its dependencies

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 method called");
        b.method();
        c.method();
        System.out.println(method2());

    }

    protected int method2() {
        return 10;
    }
}

      

Then you can write junit to do this using your parameterized class as shown below



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

      

Test class output

A method called
20

      

  • Here B

    and C

    represent the mocked object that you injected into your class A

    using the parameterized constructor.
  • Then we created spy

    from A

    called spyA

    .
  • We checked to see if it actually spy

    works by changing the return value of the protected method method2

    in the class A

    , which couldn't have been possible if spyA

    it wasn't actually spy

    from A

    .
+2


source


It looks like you are missing a dependency injection solution. Mockito is great for working with your DI to inject mocks. For example, you can use CDI, annotate your members Notification

and EntryService

with @Inject

, declare @Mock

for both in your test, and then let Mockito inject them into yours RegDao

for testing.

Here is a working mock test that I think you are 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());
    }
}

      

0


source







All Articles