vij*_*rth 7 java unit-testing mockito
在这里,我尝试模拟Service 类TestServiceImpl的自动装配字段ServiceHelper,我无法通过ServiceHelper类的模拟对象调用方法。
这是我的班级文件:
@Service
public class TestServiceImpl implements TestService {
@Autowired
private TestDAO testDAO;
@Autowired
private ServiceHelper serviceHelper;
@Override
public ResultsModel getResults(Map<String, Object> map) throws WebServiceException_Exception {
return serviceHelper.getResults(map);
}
Run Code Online (Sandbox Code Playgroud)
二等:
@Repository
public class ServiceHelper {
private static Logger logger = Logger.getLogger(ServiceHelper.class.getName());
@Autowired
ResponseHeader responseHeader;
public void setResponseHeader(ResponseHeader responseHeader) {
this.responseHeader = responseHeader;
}
public ResultsModel getResults(Map<String, Object> map) throws WebServiceException_Exception {
....
}
Run Code Online (Sandbox Code Playgroud)
和测试类:
@RunWith(MockitoJUnitRunner.class)
public class MockitoTester {
@InjectMocks
private TestServiceImpl serviceImpl = new TestServiceImpl();
@Mock
private TestDAO testDAO;
@Mock
private ServiceHelper sHelper;
@Before
public void initMocks(){
MockitoAnnotations.initMocks(this);
}
@Test
public void testResult() throws Exception {
Map<String, Object> map = new HashMap<>();
map.put("TestId", "test123");
map.put("lang", "en");
map.put("cntry", "USA");
ResultsModel results = new ResultsModel();
when(sHelper.getResults(map)).thenReturn(results);
results = serviceImpl.getResults(map);
Assert.assertEquals(results.getStatus(), "Success");
}
Run Code Online (Sandbox Code Playgroud)
在我的测试课中:
results = serviceImpl.getResults(map);
It goes to TestServiceImpl class to method :
public ResultsModel getResults(Map<String, Object> map) throws webServiceException_Exception {
return serviceHelper.getResults(map);
}
Run Code Online (Sandbox Code Playgroud)
但在这一点上:
serviceHelper.getResults(map);
Run Code Online (Sandbox Code Playgroud)
它不会进入内部serviceHelper.getResults(map)并将所有值返回为 Null。
Please suggest where I need to do changes.
Run Code Online (Sandbox Code Playgroud)
您在这里有三个选择:
选项 1 是真正的集成测试——您可以使用更多 Spring 注释来注释您的测试类@RunWith(SpringRunner.class)并控制依赖项注入。这是一个太大的主题,无法在 SO 答案中涵盖,但是如果您 Google 搜索“spring 集成测试 mockito”,就会有很多例子。
但对于单元测试,我认为最好不要涉及Spring。一个好的 Spring bean 不需要 Spring 来运行。选项 2 只是说,编写您的类,以便单元测试(以及其他任何内容)可以通过正常的 Java 方式注入依赖项(无论是模拟还是其他任何内容)。
我认为构造函数注入是最干净的:
private final ServiceHelper serviceHelper; // note: not annotated
@Autowired
public TestService(ServiceHelper serviceHelper) {
this.serviceHelper = serviceHelper;
}
Run Code Online (Sandbox Code Playgroud)
但你也可以用public void setServiceHelper(ServiceHelper helper)- 这不太好,因为该字段不能是final。
或者通过创建这个领域public——我想你知道这不好的原因。
如果您确定有一个不是由公共构造函数或设置器设置的私有字段,您可以ReflectionUtils.setField()在测试中使用 Spring 的:
@Mock
private ServiceHelper serviceHelper;
private TestService service;
@Before
public void configureService() {
service = new TestService();
Field field = ReflectionUtils.findField(TestService.class, "serviceHelper");
ReflectionUtils.setField(field, service, serviceHelper);
}
Run Code Online (Sandbox Code Playgroud)
(或者,同样,直接使用JDK的反射类,或者其他地方的反射utils)
这是显式地使用反射来破坏您已编码到类中的访问规则。我强烈推荐选项 2。
我认为问题可能是您正在对方法进行存根以返回相同的对象,然后将其分配给被测方法的结果。即(results这里的对象):
ResultsModel results = new ResultsModel();
when(sHelper.getResults(map)).thenReturn(results);
results = serviceImpl.getResults(map);
Run Code Online (Sandbox Code Playgroud)
当它尝试在 Mockito 中存根该方法时,这可能会导致某种循环混乱,并且它肯定不会使您的断言通过:
Assert.assertEquals(results.getStatus(), "Success");
Run Code Online (Sandbox Code Playgroud)
因为结果的状态永远不会在任何地方设置。
我认为您需要为存根和被测试方法的返回值创建单独的对象,并确保将存根对象设置为“成功”状态:
ResultsModel results = new ResultsModel();
results.setStatus("Success");
when(sHelper.getResults(map)).thenReturn(results);
ResultsModel returnedResults = serviceImpl.getResults(map);
Assert.assertEquals(returnedResults.getStatus(), "Success");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24109 次 |
| 最近记录: |