Atul
Atul

Reputation: 1590

How to inject Mocks into Spring Service

Environment :

Spring MVC 4

Junit

Mockito

Code :

Spring Service under test :

@Service("abhishekService")
public class AbhishekServiceImpl implements AbhisheskService {

    @Autowired
    private DaoOne daoOne;  
    @Autowired
    private DaoTwo daoTwo;
    @Autowired
    private DaoThree daoThree;
    @Autowired
    private DaoFour daoThree;

}

Junit Test :

public class AbhishekServiceImplTest {

    @Mock
    private DaoOne daoOne;  
    @Mock
    private DaoTwo daoTwo;
    @Mock
    private DaoThree daoThree;
    @Mock
    private UserDao userDao;

    private AbhisheskService abhisheskService;

    @Before
    public void setUp(){        

        MockitoAnnotations.initMocks(this);
        abhisheskService = new AbhishekServiceImpl();

    }

}

Issue :

1)As shown in code snippet one , the class under test uses four dependencies.

2)As shown in code snippet two , in junit test case class , all 4 dependencies are mocked using @Mock

3)My question is : how these four mocked objects should be injected into test class ?

4)My class under test doesn't have constructor/setter injection but field injection using @Autowired.

5)I don't want to use @InjectMocks annotation due to its dangerous behavior as mentioned here

Can anybody please guide on this ?

Upvotes: 1

Views: 612

Answers (2)

Naresh Yadav
Naresh Yadav

Reputation: 713

You are trying to test a class wrongly designed to test the behavior i.e. the properties are not accessible to be mocked. AbhishekServiceImpl has to provide a way to inject the mocks to the class. If you cannot access the fields then it is a clear case of wrongly designed class. Considering that the AbhishekServiceImpl is a class in a legacy code and you are trying to test the behaviour then you can use reflection to inject the mock objects as below:

DaoOne mockedDaoOne = mock(DaoOne.class);
    when(mockedDaoOne.doSomething()).thenReturn("Mocked behaviour");

    AbhishekService abhishekService = new AbhishekServiceImpl();
    Field privateField = PrivateObject.class.getDeclaredField("daoOne");

    privateField.setAccessible(true);

    privateField.set(abhishekService, mockedDaoOne);

    assertEquals("Mocked behaviour", abhishekService.doSomething());

Its very rare that you test behaviour of a class that you have not written yourself. Though I can imagine a use case where you have to test an external library because its author did not test it.

Upvotes: 2

Alexandru Marina
Alexandru Marina

Reputation: 906

You can mark the junit test with @RunWith(SpringJUnit4ClassRunner.class) and then use @ContextConfiguration to define a context which instantiates the DAOs and service and wires them together.

Upvotes: 0

Related Questions