Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock classes with constructor injection

How to get constructor injection in Mockito

I have the following class:

class A {

  private B mB;

  A(B b) {
     mB = b;
  }

 void String someMethod() {
     mB.execute();
  }
}

how do I test someMethod using a mock class A and class B using

B b = Mockito.mock(B.class)
Mockito.when(b.execute()).thenReturn("String")

A a = Mockito.mock(A.class)
//somehow inject b into A and make the below statement run
Mockito.when(a.someMethod()).check(equals("String"))
   
like image 854
ir2pid Avatar asked May 23 '18 09:05

ir2pid


3 Answers

You need create real A class because you want to test it but you need to mock other classes used in A class. Also, you can find mockito documentation says that don't mock everything.

class ATest {
        @Mock
        private B b;
        private A a;
        @Before
        public void init() {
            MockitoAnnotations.initMocks(this);
            a = new A(b);
        }
        @Test
        public String someMethodTest() {
            String result = "result";
            Mockito.when(b.execute()).thenReturn(result);
            String response = a.someMethod();
            Mockito.verify(b,  Mockito.atLeastOnce()).execute();
            assertEquals(response, result);
        }
    }
like image 200
Hatice Avatar answered Oct 19 '22 18:10

Hatice


You want to test someMethod() of class A. Testing the execute() of class B should take place in the other test, because instance of B is a dependency in your case. Test for execute() should be made in different test.

You don't need to test how B object will behave, so you need to mock it and afterwards, check that execute() was invoked.

So in your case your test will look something like this:

  B b = Mockito.mock(B.class);
  A a = new A( b );
  a.someMethod();
  Mockito.verify( b, Mockito.times( 1 ) ).execute();
like image 6
Rostislav V Avatar answered Oct 19 '22 18:10

Rostislav V


Another way of injecting a mock to real object (as A should be a real object) is to use annotations, they will create objects you want:

@Mock 
B mockOfB;

@InjectMocks
A realObjectA;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

Then, like they said, run the method you want to test without mockito (because you want to test it, so call it on real instance) and check the result according to your expectations.

Behaviour of object B can be mocked in any way, to satisfy your needs.

like image 6
staszko032 Avatar answered Oct 19 '22 17:10

staszko032