简体   繁体   English

模拟类特定方法(其余的应该是真实的)

[英]Mock class specific methods (the rest should be real)

I have a class that I want to test, and also mock a specific method.我有一个要测试的类,并且还要模拟一个特定的方法。 I've created a spy as follows:我创建了一个间谍,如下所示:

CredentialsService partialMock = spy(CredentialsService.class);

And call in my test to a method I want to test: partialMock.process(client, id, url, null, userDetails);并在我的测试中调用我想要测试的方法: partialMock.process(client, id, url, null, userDetails);

In real method:在实际方法中:

@Autowired private EncryptionService encryptionService; My rest fails on NullPointerException, because one of the autowires of the class is NULL .我的休息在 NullPointerException 上失败了,因为该类的自动连线之一是NULL In this line:在这一行:

Credential credentials = new Credential(id, encryptionService, tokenResponseParams.getAccessToken(), tokenResponseParams.getRefreshToken(), tokenResponseParams.getExpiresIn());
 

encryptionService is null and one of the operation in creating the Credential class fail on this. encryptionService为空,创建Credential类的操作之一在此失败。

Any idea why my spy does not keep the real instance of encryptionService as a bean, and how I can fix it?知道为什么我的间谍没有将真实的encryptionService实例保留为 bean,以及如何修复它吗?

You are creating a spy using only a class parameter in the spy() method, so Mockito does not know about any object that should be injected into the created spy object.您只使用spy()方法中的类参数创建间谍,因此 Mockito 不知道应该注入创建的间谍对象的任何对象。

To inject the missing dependency you can pick one of three approaches (one without modification of the actual code).要注入缺少的依赖项,您可以选择三种方法之一(一种无需修改实际代码)。 For the sake of simplification in the example I've stripped the objects as complete code was not provided.为了简化示例,我已经剥离了对象,因为没有提供完整的代码。


Let's assume field injection first ( here's more on why it's discouraged to use field injection ):让我们先假设场注入( 这里有更多关于为什么不鼓励使用场注入):

class EncryptionService {

    void encrypt() {
        System.out.println("Encrypted!");
    }
}

class CredentialsService {

    EncryptionService encryptionService;

    void process() {
        encryptionService.encrypt();
    }
}

Annotations注释

@Mock // or @Spy, or actual object
EncryptionService encryptionService;
@Spy
@InjectMocks // this tells Mockito to inject dependencies
CredentialsService credentialsService;

@BeforeEach
void setUp() {
    // here the injection actually happens
    // openMocks() in more recent versions of Mockito
    MockitoAnnotations.initMocks(this);
}

@Test
void annotationInjection() {
    credentialsService.process();
}

For both approaches below we will need the dependencies to be injected in a constructor, so CredentialsService looks like this:对于以下两种方法,我们都需要将依赖项注入到构造函数中,因此CredentialsService如下所示:

class CredentialsService {

    EncryptionService encryptionService;

    CredentialsService(EncryptionService encryptionService) {
        this.encryptionService = encryptionService;
    }

    void process() {
        encryptionService.encrypt();
    }
}

Mock settings模拟设置

@Test
void mockWithSettings() {
    var credentialsService = mock(CredentialsService.class, withSettings()
            // EncryptionService could be also a mock or a spy
            .useConstructor(new EncryptionService())
            // actually acts like a spy thanks to the below setting
            .defaultAnswer(CALLS_REAL_METHODS));
    
    credentialsService.process();
}

( read more in the Mockito documentation ) 在 Mockito 文档中阅读更多内容


Spy on an object监视一个对象

@Test
void spyOnObject() {
    var encryptionService = mock(EncryptionService.class);
    var credentialsService = spy(new CredentialsService(encryptionService));

    credentialsService.process();
}

I'm usually using the first or last approach from the ones above (but the first one with dependencies injected by constructor - it works as well).我通常使用上述方法中的第一种或最后一种方法(但第一种方法是由构造函数注入依赖项 - 它也可以)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM