如何将模拟注入Spring Service

时间:2016-07-16 19:16:45

标签: spring junit mockito

环境:

Spring MVC 4

Junit

Mockito

代码:

正在测试的Spring服务:

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

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

}

Junit测试:

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

    }

}

问题:

1)如代码片段1所示,被测试的类使用四个依赖项。

2)如代码片段2所示,在junit测试用例类中,使用@Mock

模拟所有4个依赖项

3)我的问题是:如何将这四个模拟对象注入测试类?

4)我的测试类没有构造函数/ setter注入,而是使用@Autowired.进行字段注入

5)由于其危险行为,我不想使用@InjectMocks注释 as mentioned here

有人可以指导吗?

2 个答案:

答案 0 :(得分:2)

您正在尝试测试错误设计的类来测试行为,即无法模拟属性。 AbhishekServiceImpl必须提供一种方法将模拟注入课堂。如果您无法访问这些字段,那么这是一个错误设计的类的明显案例。考虑到AbhishekServiceImpl是遗留代码中的一个类,并且您正在尝试测试行为,那么您可以使用反射来注入模拟对象,如下所示:

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

您很少测试自己没有编写过的类的行为。虽然我可以想象一个用例,你必须测试一个外部库,因为它的作者没有测试它。

答案 1 :(得分:0)

您可以使用@RunWith(SpringJUnit4ClassRunner.class)标记junit测试,然后使用@ContextConfiguration定义实例化DAO和服务并将它们连接在一起的上下文。