java(eclipse)中的junit测试错误-设置“当...”不起作用

问题描述 投票:0回答:1

在我的测试设置中,该行:

when(kc.getToken()).thenReturn(token);   

不起作用,我从

ServiceImplementation
收到以下错误:

java.lang.NullPointerException: Cannot invoke "services.KeycloakService.getToken()" because "this.kc" is null

我正在使用以下依赖项:

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.mockito:mockito-core:5.14.2'
    testImplementation 'org.mockito:mockito-junit-jupiter:5.14.2'

我尝试过的:

  • 运行“testMockInjection”:所有测试都是绿色的。
  • 运行 testUpdate:我看到服务实现中的代码停在了线上
String zaToken = kc.getToken

并给出上述错误

  • 设置中的消息按预期打印
  • 我尝试使用间谍而不是模拟,但它再次不起作用。另外,据我了解,最好使用模拟,因为我想“伪造”整个服务并且只需要存根一个函数。
  • 测试导入是否正确
  • 我正在使用
    @ExtendWith(MockitoExtension.class)
    @BeforeEach
    @InjectMocks
    ,它们在我的其他测试中有效。

但是,我也尝试了 MockitoAnnotations.initMocks(this) ,错误仍然存在。

服务实施代码


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
...
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
...
import services.AasService;
import services.KeycloakService;
 
@Service
public class AasServiceImpl implements AasService{
    private final RestTemplate restTemplate;
    
    @Autowired
    private KeycloakService kc;

    @Value("${ass.server}")
    private String aasUri;
    @Value("${ass.id}")
    private String aasIdShort;
    
    public AasServiceImpl (RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    
    @Override
    public void update(String applicationUri, String nodeId, JSONObject value) {
        System.out.println(applicationUri);
        System.out.println(nodeId);
        System.out.println(value);

        String submodelElementValueId = applicationUri.replace(":", "_") + nodeId.replace("i=", "");
        
        System.out.println(submodelElementValueId);
        
        if (kc instanceof KeycloakServiceImpl) {
            System.out.println("This is original service.");
        } else {
            System.out.println("This is  not the original service.");
//this is the option printed 

        }
//problematic line is the following                 
        String zaToken = kc.getToken();
        
//this is not printed in the code 
        System.out.println(zaToken);
        try {
            updateValue("DefectDetectionSkill", "Inputs", submodelElementValueId, value, zaToken);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    }
}

测试代码:

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
...
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
...
import org.junit.jupiter.api.BeforeEach;
import services.KeycloakService;  //this is an interface

@ExtendWith(MockitoExtension.class)
public class AasServiceImplTest {

    @Mock
    private KeycloakService kc;
    
    @Mock
    private RestTemplate restTemplate;
        
    @InjectMocks
    private AasServiceImpl aasService;

    @BeforeEach
    void setUp() {
       
        String token = "mockToken";
        when(kc.getToken()).thenReturn(token);

        ResponseEntity<String> response= new ResponseEntity<>("", HttpStatus.OK);
        when(restTemplate.exchange(anyString(), any(), any(), eq(String.class))).thenReturn(response);
 
        System.out.println("set up runs");
        //this message is printed
    }

    /*
    @Test
    void testMockInjection() {
        
        assertNotNull(kc, "KeycloakService mock is not injected!");
        assertNotNull(restTemplate, "RestTemplate mock is not injected!");
        assertNotNull(aasService, "AasServiceImpl is not initialized!");
    }
    
    */
    @Test
    void testUpdate() {
        
        //Arrange
        String applicationUri = "http://mock_uri";
        String nodeId="i=ioanna";
        JSONObject value = new JSONObject();
        value.put("Value", 1234);

        //Act
        aasService.update(applicationUri,  nodeId , value);
        System.out.println("Value: " + value.get("Value"));

        //Assert
        assertNotNull(kc, "KeycloakService mock is not injected!");

        //verify(kc, times(1)).getToken();
        //verify(restTemplate, atLeastOnce()).exchange(anyString(), any(), any(), eq(String.class));
    }
java unit-testing testing nullpointerexception mockito
1个回答
0
投票

看起来

@InjectMock
未能混合字段注入和构造函数参数注入。要么自动连接
restTemplate
kc
字段:

@Service
public class AasServiceImpl implements AasService {
    // No explicit constructor!

    @Autowired
    private  RestTemplate restTemplate;

    @Autowired
    private KeycloakService kc;
    ...

或者将它们都作为构造函数参数:

@Service
public class AasServiceImpl implements AasService {
    private  RestTemplate restTemplate;
    private KeycloakService kc;


    public AasServiceImpl (RestTemplate restTemplate, KeycloakService kc) {
        this.restTemplate = restTemplate;
        this.kc = kc;
    }
    ...
© www.soinside.com 2019 - 2024. All rights reserved.