gpt4 book ai didi

java - Junit 5 @MockBean 中的 NullPointerException

转载 作者:行者123 更新时间:2023-12-04 08:38:37 26 4
gpt4 key购买 nike

我在我的 Spring Boot 应用程序中为我的服务编写了一个 JUnit 5 测试。
我将@MockBean 用于模拟 PasswordEncoder 和其他 bean,但我获得了 NullPointerException。
我总是在“何时”调用期间获得 NullPointerException:when(compteRepository.getByLogin(anyString())).thenReturn(Optional.of(acc));
服务

package com.compte.application.impl;

import com.compte.application.CompteService;
import com.compte.domain.exceptions.EntityNotFoundExcpetion;
import com.compte.domain.model.Compte;
import com.compte.domain.model.CompteUpdatedData;
import com.compte.domain.repository.CompteRepository;
import com.compte.domain.utils.CompteUtil;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.time.LocalDate;
import java.util.Optional;

/**
* @author mbint
*/
@AllArgsConstructor
public class CompteServiceImpl implements CompteService{

private final static Logger LOGGER = LoggerFactory.getLogger(CompteService.class);

private CompteRepository CompteRepository;
private PasswordEncoder passwordEncoder;

@Override
public Optional<Compte> getByLogin(String login) {
return CompteRepository.getByLogin(login);
}

@Override
public void update(final Long id, CompteUpdatedData updatedData) {
Optional<Compte> optional = CompteRepository.getById(id);
if(optional.isPresent()) {
Compte Compte = optional.get();
Compte.setFirstName(updatedData.getFirstName());
Compte.setLastName(updatedData.getLastName());
CompteRepository.save(Compte);
} else {
throw new EntityNotFoundExcpetion("Compte: " + id + " not found !!");
}
}
}
Junit 测试
package com.compte.application;

import com.compte.application.impl.CompteServiceImpl;
import com.compte.domain.model.Compte;
import com.compte.domain.model.CompteUpdatedData;
import com.compte.domain.repository.compteRepository;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.mockito.Mockito.*;


/**
* @author mbint
*/
public class CompteServiceImplTest {

private final static String PASSWORD = "Passw00rd";

@MockBean
private compteRepository compteRepository;
@MockBean
private PasswordEncoder passwordEncoder;
private CompteService CompteService = new CompteServiceImpl(compteRepository, passwordEncoder);

@DisplayName(("Should return existing user"))
@Test
private void given_login_then_return_existing_user() {
Compte acc = Compte.builder().id(1L)
.firstName("Luc")
.lastName("JOJO")
.login("xxx@gmail.com")
.password("xxxxxxxxxxxxxxx")
.build();
when(compteRepository.getByLogin(anyString())).thenReturn(Optional.of(acc));

Optional<Compte> optional = CompteService.getByLogin("xxx@gmail.com");
Compte Compte = optional.get();

Assertions.assertSame(1L, acc.getId());
Assertions.assertSame("xxx@gmail.com", Compte.getLogin());
}

@DisplayName("Should update existing user")
@Test
public void given_edited_Compte_then_update_user() {
Compte acc = Compte.builder().id(1L)
.firstName("Luc")
.lastName("JOJO")
.email("xxx@gmail.com")
.password("xxxxxxxxxxxxxxx")
.build();
when(compteRepository.getById(anyLong())).thenReturn(Optional.of(acc));

CompteUpdatedData updatedData = CompteUpdatedData.builder()
.firstName("Moos")
.lastName("Man")
.build();
CompteService.update(1L, updatedData);
Assertions.assertSame("Moos", acc.getFirstName());
}

private List<Compte> getComptes() {
List<Compte> Comptes = new ArrayList<>();

Compte acc1 = Compte.builder()
.id(1L)
.firstName("Luc")
.lastName("JOJO")
.email("xxx@gmail.com")
.login("xxx@gmail.com")
.build();
Comptes.add(acc1);

Compte acc2= Compte.builder()
.id(2L)
.firstName("Jean")
.lastName("KELLY")
.email("jean.kelly@gmail.com")
.login("jean.kelly@gmail.com")
.build();
Comptes.add(acc2);

Compte acc3= Compte.builder()
.id(3L)
.firstName("Marc")
.lastName("BARBY")
.email("marc.barby@gmail.com")
.login("marc.barby@gmail.com")
.build();
Comptes.add(acc3);

return Comptes;
}

}
Spring 启动应用程序
package com.compte;

import com.compte.application.CompteService;
import com.compte.application.impl.CompteServiceImpl;
import com.compte.domain.repository.CompteRepository;
import com.compte.infrastructure.repository.database.CompteDBRepositiry;
import com.ombsc.bargo.common.config.SwaggerConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.hateoas.client.LinkDiscoverer;
import org.springframework.hateoas.client.LinkDiscoverers;
import org.springframework.hateoas.mediatype.collectionjson.CollectionJsonLinkDiscoverer;
import org.springframework.plugin.core.SimplePluginRegistry;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;
import java.util.List;

@ComponentScan({"com.compte.interfaces.interfaces"})
@SpringBootApplication
@Import({SwaggerConfig.class})
public class CompteApplication {

public static void main(String[] args) {
SpringApplication.run(CompteApplication.class, args);
}

@Bean
public CompteRepository getRepository() {
return new CompteDBRepositiry();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}


@Bean
public CompteService CompteService(CompteRepository repository, PasswordEncoder passwordEncoder) {
return new CompteServiceImpl(repository, passwordEncoder);
}

@Bean
public LinkDiscoverers discovers() {
List<LinkDiscoverer> plugins = new ArrayList<>();
plugins.add(new CollectionJsonLinkDiscoverer());
return new LinkDiscoverers(SimplePluginRegistry.create(plugins));
}
}

最佳答案

模拟需要在使用之前进行初始化。有几个选项可以做到这一点。
第一个选项是使用 @SpringExtension这将初始化带有 @MockBean 注释的模拟:

@ExtendWith(SpringExtension.class)
public class CompteServiceImplTest {
@Autowired
private CompteService CompteService;

@MockBean
private compteRepository compteRepository;

// ...
}
这将确保在 Autowiring 服务 bean 之前模拟存储库 bean。
但是,由于您正在为服务编写单元测试,因此根本不需要 Spring 扩展。第二个选项是使用 @Mock而不是 @MockBean , 并调用 @InjectMocks结合 MockitoExtension用于构建被测服务:
@ExtendWith(MockitoExtension.class)
public class CompteServiceImplTest {
@InjectMocks
private CompteService CompteService;
@Mock
private compteRepository compteRepository;

// ...
}
或者,您可以调用 MockitoAnnotations.initMocks() , 这将初始化带有 @Mock 注释的模拟,并为您的服务使用构造函数注入(inject):
public class CompteServiceImplTest {
private CompteService CompteService;

@Mock
private compteRepository compteRepository;

@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
CompteService = new CompteServiceImpl(compteRepository, ...);
}

// ...
}
最后,您可以通过调用 Mockito.mock() 来完成所有操作而无需注释。直接地:
public class CompteServiceImplTest {
private compteRepository compteRepository;

@BeforeEach
void setUp() {
compteRepository = Mockito.mock();
CompteService = new CompteServiceImpl(compteRepository, ...);
}

// ...
}

关于java - Junit 5 @MockBean 中的 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64672608/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com