spring-boot - 如果在我们正在测试的方法中使用新关键字声明实例,我们可以模拟它吗?
问题描述
我是 Mockito 和 Junit 的新手,我正在使用 Spring Boot
我想知道如果实例使用我们正在测试的方法中的新关键字声明,我们可以模拟它吗?
例如:
@Service
class A {
@Autowired
X x;
@Autowired
Y y;
public void testMe(){
imCommunicatingWithSomeRestClient();
}
private void imCommunicatingWithSomeRestClient(){
String body="";
MyRestClient client=new MyRestClient(iTakeUrlNeedsToHit); //no arg constructor not exist and suppose this is the method of some Core jar project
client.callDataRest(HTTP.GET,body)
}
}
尽管我想模拟它,但我已经尝试了 all @Spy
@Mock
,@InjectMocks
以检查它的行为是否会有所不同,但这些都不适合我,因为它总是创建一个新对象并调用真实方法。
所以我稍微改变了方法,并使用BeanFactory来代替 new 我将其替换为:
MyRestClient client=beanFactory.getBean(MyRestClient.class,jobDataRestUrl);
所以我有这些问题:
上面已经问过(如果我们模拟实例,如果它使用我们正在测试的方法内部的 new 关键字声明)。
如果我当前的项目是Spring Boot项目并且MyRestClient在核心编写的 jar 中。标准是否说我不应该由 Bean Factory 创建它,因为我认为我应该这样做并让 Spring 处理它
我什至尝试过反射,但它似乎也不适用于在方法内使用 new 关键字创建的实例,而不是在类级别上。
解决方案
您当前的设置无法有效测试。您仍然可以使用许多奇怪的解决方法来做到这一点,但仍然不推荐。这是你可以做的;首先,你的类中不应该有任何类型的依赖初始化(比如new MyRestClient(...)
)。因此,将 REST 客户端移动到属性级别并通过构造函数将其注入。
@Service
class A {
private final X x;
private final Y y;
private final MyRestClient restClient;
public A (X x, Y y, MyRestClient restClient) {
this.x = x;
this.y = y;
this.restClient = restClient;
}
public void testMe() {
imCommunicatingWithSomeRestClient();
}
private void imCommunicatingWithSomeRestClient() {
String body = "";
restClient.callDataRest(GET, body);
}
}
由于您使用的是 Spring,因此您可以创建 REST 客户端的 bean 并将端点 URL 移动到外部属性。
class Config {
@Bean
public MyRestClient myRestClient(@Value("${property.name}") String url) {
return new MyRestClient(url);
}
}
最后,您可以轻松地模拟该 REST 客户端的行为。
@ExtendWith(MockitoExtension.class)
class TestA {
@Mock
private X x;
@Mock
private Y y;
@Mock
private MyRestClient restClient;
@InjectMocks
private A a;
// your tests...
}