首页 > 解决方案 > 如果在我们正在测试的方法中使用新关键字声明实例,我们可以模拟它吗?

问题描述

我是 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); 

所以我有这些问题:

  1. 上面已经问过(如果我们模拟实例,如果它使用我们正在测试的方法内部的 new 关键字声明)。

  2. 如果我当前的项目是Spring Boot项目并且MyRestClient在核心编写的 jar 中。标准是否说我不应该由 Bean Factory 创建它,因为我认为我应该这样做并让 Spring 处理它

  3. 我什至尝试过反射,但它似乎也不适用于在方法内使用 new 关键字创建的实例,而不是在类级别上。

标签: spring-bootjunitmockitopowermockito

解决方案


您当前的设置无法有效测试。您仍然可以使用许多奇怪的解决方法来做到这一点,但仍然不推荐。这是你可以做的;首先,你的类中不应该有任何类型的依赖初始化(比如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...
}

推荐阅读