gpt4 book ai didi

java - 如何使用 mockito 模拟 Autowiring 字段

转载 作者:行者123 更新时间:2023-12-04 13:23:07 24 4
gpt4 key购买 nike

在这里,我试图模拟服务类 TestServiceImpl 的 Autowiring 字段 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);
}

第二类:
@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 {
....
}

和测试类:
@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");
}

在我的测试课中:
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);
}

但在这一点上:
serviceHelper.getResults(map); 

它不会进入 serviceHelper.getResults(map) 并将所有值返回为 Null。
Please suggest where I need to do changes.

最佳答案

您在这里有三个选择:

  • 在您的测试中进行实际的 Spring Autowiring
  • 使用可以由您的测试合法执行的注入(inject)方法(构造函数参数、公共(public) setter 、公共(public)字段 - 按优先顺序)
  • 使用反射注入(inject)你的模拟


  • 选项 1 是真正的集成测试——您可以使用 @RunWith(SpringRunner.class) 注释您的测试类并使用更多的 Spring 注解来控制依赖注入(inject)。这是一个太大的主题,无法在 SO 答案中涵盖,但是如果您在 Google 上搜索“spring 集成测试 mockito”,则会有很多示例。

    但是对于单元测试,我认为最好不要涉及 Spring。一个好的 Spring bean 不需要 Spring 来运行。选项 2 只是说,编写您的类,以便单元测试(和其他任何东西)可以通过正常的 Java 方式注入(inject)依赖项(无论是模拟还是其他任何东西)。

    在我看来,构造函数注入(inject)是最干净的:
    private final ServiceHelper serviceHelper; // note: not annotated

    @Autowired
    public TestService(ServiceHelper serviceHelper) {
    this.serviceHelper = serviceHelper;
    }

    但是您也可以使用 public void setServiceHelper(ServiceHelper helper) 来做到这一点。 -- 这个不太好,因为字段不能是 final .

    或者通过制作字段 public ——我想你知道这不好的原因。

    如果您决定拥有一个不是由公共(public)构造函数或 setter 设置的私有(private)字段,您可以使用 Spring 的 ReflectionUtils.setField()从您的测试中:
     @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);
    }

    (或者,同样,直接使用 JDK 的反射类,或其他地方的反射实用程序)

    这是明确地使用反射来破坏您编码到类中的访问规则。我彻底推荐选项2。

    关于java - 如何使用 mockito 模拟 Autowiring 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46324098/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com