我是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)
}
}
虽然我想模拟它,但我已经试过了所有的方法。@Spy
@Mock
, @InjectMocks
来检查它是否会有不同的行为,但这些对我来说都不起作用,因为它总是创建一个新的对象并调用真正的方法。
所以我稍微改变了一下方法,使用了 BeanFactory 而不是新的,我把它替换成:
MyRestClient client=beanFactory.getBean(MyRestClient.class,jobDataRestUrl);
所以我有这些问题。
上面已经问过了(如果我们模拟实例,如果它用new关键字声明,那就在我们测试的方法里面)。
如果我当前的项目是 弹簧靴 计划和 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...
}