如何使用mockito模拟@Value字段



我正在尝试测试一个方法,但当我的测试方法调用实际方法时,由于存在@Value字段,实际方法总是接收在@Value字段下定义的值,即null。您可以查看以下实际方法和测试方法的代码:

实际方法

public class IndexService {
@Value("${elasticsearch.index}")
private String index;
public boolean index(String id, String json, String index) {
try {
createIndex();
return true;
} catch (IOException e) {
log.warn("Exception in indexing data {}", e.getMessage());
}
return false;
}
private void createIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest(index);
}
}

以下是我的测试方法:

@Test
public void IndexServiceIndex() throws IOException {
CreateIndexRequest request1 = new CreateIndexRequest(index);
request1.source("{"name":true}",XContentType.JSON);
Mockito.when(indicesClient.create(request1,RequestOptions.DEFAULT))
.thenReturn(createIndexResponse);
Boolean indexser = indexService.index("65","{"name":molly}","1");
}

以下是CreateIndexRequest class方法:

public CreateIndexRequest(String index) {
if (index == null) {
throw new IllegalArgumentException("The index name cannot be null.");
} else {
this.index = index;
}
}

实际情况是,当我的测试方法调用实际方法indexService.index("65","{"name":molly}","1");时,控制转到actual method,而私有方法createIndex正在注入index值,该值在上面定义为@Value("${elasticsearch.index}") private String index;。因此在CreateIndexRequest method中它总是评估为null并抛出异常IllegalArgumentException("The index name cannot be null.")

我尝试使用ReflectionTestUtils.setField,但在我的项目中没有org.springframework.test.util.ReflectionTestUtils所需的依赖项。还有其他方法可以模拟@Value字段吗?

您根本不需要。一般来说,使用字段注入是不可取的,因为它会使测试代码变得更加复杂

  1. 构造函数注入-您可以在构造函数参数上@Value,并且可以通过构造函数放置测试值
  2. setter注入-用@Value注释setter方法。它在容器中的工作方式完全相同,如何在测试中使用它是显而易见的
  3. 使用@TestProperties-但这将修复整个测试类的值
  4. 使用反射-这甚至允许您更改最终字段,但是如果涉及到AOP和代理,这可能不会简单地起作用

可能还有其他许多。我认为1和2是最可行的方法。

最新更新