Ous*_*NTE 11 java spring spring-boot junit5
我在 Spring Boot 应用程序中为我的服务编写了 JUnit 5 测试。我曾经@MockBean模拟PasswordEncoder和其他豆子,但我获得了NullPointerException.
我总是在通话过程中收到 NullPointerException when:
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 !!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
联合测试
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;
    }
}
Run Code Online (Sandbox Code Playgroud)
春季启动应用程序
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));
    }
}
Run Code Online (Sandbox Code Playgroud)
    Arh*_*nen 13
模拟需要在使用之前进行初始化。有多种选择可以做到这一点。
第一个选项是使用@SpringExtension它将初始化带有注释的模拟@MockBean:
@ExtendWith(SpringExtension.class)
public class CompteServiceImplTest {
    @Autowired
    private CompteService CompteService;
    @MockBean
    private compteRepository compteRepository;
    // ...
}
Run Code Online (Sandbox Code Playgroud)
这将确保在自动装配服务 bean 之前模拟存储库 bean。
但是,由于您正在为该服务编写单元测试,因此根本不需要 Spring 扩展。第二个选项是使用@Mock代替@MockBean,并@InjectMocks与 一起调用MockitoExtension来构建被测试的服务:
@ExtendWith(MockitoExtension.class)
public class CompteServiceImplTest {
    @InjectMocks
    private CompteService CompteService;
    @Mock
    private compteRepository compteRepository;
    // ...
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以只调用MockitoAnnotations.initMocks(),这将初始化用 注释的模拟@Mock,并为您的服务使用构造函数注入:
public class CompteServiceImplTest {
    private CompteService CompteService;
    @Mock
    private compteRepository compteRepository;
    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);
        CompteService = new CompteServiceImpl(compteRepository, ...);
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)
最后,您可以直接调用而无需注释来完成这一切Mockito.mock():
public class CompteServiceImplTest {
    private compteRepository compteRepository;
    @BeforeEach
    void setUp() {
        compteRepository = Mockito.mock();
        CompteService = new CompteServiceImpl(compteRepository, ...);
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)
编辑:
自 Mockito 3 起,MockitoAnnotations.initMocks()已被弃用,取而代之的是MockitoAnnotations.openMocks(). 此方法返回一个实例,AutoCloseable可用于在测试后关闭资源。
public class CompteServiceImplTest {
    private CompteService CompteService;
    @Mock
    private compteRepository compteRepository;
    private AutoCloseable closeable;
    @BeforeEach
    void setUp() {
        closeable = MockitoAnnotations.openMocks(this);
        CompteService = new CompteServiceImpl(compteRepository, ...);
    }
    @AfterEach
    void tearDown() {
        closeable.close();
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           15902 次  |  
        
|   最近记录:  |