Why i get null insted of mock? - spring-boot

I have a project with follwing classes:
#Repository
public interface SensorRepository extends JpaRepository<Sensor, Long> {
}
#Service
#RequiredArgsConstructor
public class SensorsServiceImpl implements SensorService {
private final SensorRepository sensorRepository;
#Override
#Transactional
public Sensor save(Sensor sensor) {
return sensorRepository.save(sensor);
}
...
}
I created test to try Mockito
#RunWith(MockitoJUnitRunner.class)
class SensorsServiceImplTest {
#Mock
private SensorRepository sensorRepository;
#InjectMocks
private SensorService sensorService;
#Test
public void wasSensorSaved(){
Sensor sensor = Sensor.builder().id(1L).build();
when(sensorRepository.save(sensor)).thenReturn(sensor);
Sensor savedSensor = sensorService.save(sensor);
assertThat(savedSensor).isNotNull();
}
}
But when i run this test, i get excpetion, what sensorRepository is not mock, it is null.
If i get mock right in test, like
SensorRepository sensorRepository1 = mock(SensorRepository.class);
SensorService sensorService1 = new SensorsServiceImpl(sensorRepository1);
it works correctly. Where can be a problem?

I solved it adding annotation #SpringBootTest

Related

Mockito: How to properly mock a List of Spring Services

I have the following Spring Service class that I'm trying to test with Mockito:
#Service
public class ObjectExportService {
#Autowired
protected List<SecuredService<? extends SecuredObject>> securedServices;
public void doStuff() {
for(int i = 0; i < this.securedServices.size(); i++){
SecuredService<? extends SecuredObject> securedSrv = this.securedServices.get(i);
//this access works
}
for (SecuredService<? extends SecuredObject> securedSrv : this.securedServices) { //this access does not work
}
}
}
This is my Test class for that service:
#RunWith(MockitoJUnitRunner.class)
public class ObjectExportServiceTest {
#InjectMocks
private ObjectExportService objectExportService;
#Mock
protected List<SecuredService<? extends SecuredObject>> securedServices;
#Test
public void testDoStuff(){
objectExportService.doStuff();
Assert.assertTrue(true);
}
}
When I run the test, I get a NullpointerException, but only in the for-each loop.
First I assumed is a similar problem as described in this thread:
I have Mocked the List and would therefore need to mock the iterator() call.
The solutions provided in that thread didn't work for me, because I am actually autowiring a List.
So I stumbled across this solution in another thread. Simply changing the #Mock to #Spy resolved the issue for me:
#RunWith(MockitoJUnitRunner.class)
public class ObjectExportServiceTest {
#InjectMocks
private ObjectExportService objectExportService;
#Spy // <-- change here
protected List<SecuredService<? extends SecuredObject>> securedServices;
#Test
public void testDoStuff(){
objectExportService.doStuff();
Assert.assertTrue(true);
}
}

Mockito injecting mocks Spring Boot test

Hi I have a service class that contains mapper and repository:
#Service
public class ProductServiceImp implements ProductService {
#Autowired
private ProductRepository repository;
#Autowired
private WarehouseApiMapper mapper;
public ProductServiceImp(ProductRepository repository) {
this.repository = repository;
}
}
Repository:
#Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {
}
Mapper:
#Mapper(componentModel = "spring")
public interface WarehouseApiMapper {
WarehouseApiMapper mapper = Mappers.getMapper(WarehouseApiMapper.class);
Product ProductDtoToProduct(ProductDto productDto);
ProductDto ProductToProductDto(Product product);
}
In test class I would like to inject mock repository and autowired mapper
Here is my test class:
#SpringBootTest
public class ProductServiceTest {
#Mock
ProductRepository repository;
#InjectMocks
ProductServiceImp service;
#ParameterizedTest
#MethodSource("provideParametersProductUpdate")
void assert_that_product_is_updated_correctly(String productName, BigDecimal productPrice) {
Product oldProduct = new Product("Product that does not exist", BigDecimal.valueOf(1000000), null);
oldProduct.setId(1);
Mockito.when(repository.findById(1)).thenReturn(Optional.of(oldProduct));
Product newProduct = new Product(productName, productPrice, null);
newProduct.setId(1);
ProductDto updatedProduct = service.updateProduct(newProduct);
Assertions.assertEquals(productPrice, updatedProduct.getPrice());
Assertions.assertEquals(productName, updatedProduct.getName());
}
private static Stream<Arguments> provideParametersProductUpdate() {
return Stream.of(
Arguments.of("dark chocolate", BigDecimal.valueOf(3.2)),
Arguments.of("chewing gum", BigDecimal.valueOf(1.2)),
Arguments.of("lollipop", BigDecimal.valueOf(4.0))
);
}
}
Code throws NullPointerException when is trying to map object in service method.
Somebody knows how can I inject this? Thanks for ur answers
If you want to create just a Mockito test you could use the annotation #RunWith(MockitoJUnitRunner.class) instead of #SpringBootTest.
But if you want to create a Spring Boot integration test then you should use #MockBean instead of #Mock and #Autowired instead of #InjectMocks.

Mockito throwing a NullPointer Exception testing Service Layer

I'm trying to learn mockito by testing a service layer, but
CarServiceTest.java
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(classes = {CarService.class})
public class CarServiceTest {
#InjectMocks
private CarService carService;
#Mock
private CarRepository carRepository;
#Test
public void getCarDetails_returnsCarInfo() {
//Mockito.when **** is not able to mock, not sure why.
Mockito.when(this.carRepository.findByName("prius")).thenReturn(new Car("prius","hybrid"));
Car expected = new Car("prius", "hybrid");
//Car expected = carService.getCarDetails("prius");
Assertions.assertThat(expected.getName()).isEqualTo("prius");
Assertions.assertThat(expected.getType()).isEqualTo("hybrid");
}
CarService.java
#Service
public class CarService {
#Autowired
CarRepository carRepository;
public Car getCarDetails(String name) {
Car car = carRepository.findByName(name);
if (car == null) {
throw new CarNotFoundException();
}
System.out.println(car.getName());
return car;
}
CarRepository.java
#Repository
public class CarRepository {
public Car findByName(String name) {
if (name.equals("prius")){
Car car = new Car("prius", "hybrid");
return car;
} else {
throw new CarNotFoundException();
}
}
#InjectMocks won't inject into #Autowired fields. Change CarService to constructor injection.
Turned out was importing org.junit.jupiter.api.Test, I changed to org.junit.Test and it worked fine.

Spring injection: #MockBean #Repository is not injected

I'm trying to #MockBean a #Repository annotated class:
#Repository
public interface ApplicationDao extends MongoRepository<Application, String> {}
I'm injecting it into a #Service annotated class:
#Service
public class AuthorizationService {
private ApplicationDao appsDao;
private List<Application> allowedApplications;
#Autowired
public AuthorizationService(ApplicationDao appsDao) {
this.appsDao = appsDao; //<<MOCKED INJECTED BEAN>>
this.fillApplications();
}
private void fillApplications() {
this.appsDao.findAll() //<<MOCKED method>>
.forEach(entry -> {
this.allowedApplications.put(entry.getName(), entry);
});
}
public bool isAuthorized(Application application) {
return this.allowedApplications
.stream()
.anyMatch(app -> app.getId().equals(application.getId()));
}
}
My test mocking configuration looks like:
#RunWith(SpringRunner.class)
#SpringBootTest()
public class GroupReferencesTest {
private #Autowired AuthorizationService;
private #MockBean ApplicationDao applicationDao;
#Before
public void setUp() {
Application testApplication = new Application();
testApplication.setName("test-application");
List<Application> allowedApplications = new ArrayList<Application>();
allowedApplications.add(testApplication);
Mockito
.when(this.applicationDao.findAll())
.thenReturn(allowedApplications);
}
#Test
public void test() {
Application app = new Application();
app.getId("test-application");
assertTrue(this.authorizationService.isAuthorized(app)); //<<FAILS>>
}
}
Nevertheless, my mocked object is not injected. I mean, when my AuthorizationService calls its injected ApplicationDao is returns an empty list instead of my mocked list.
I've tried to use #MockBean(name="applicationDao") as well. The behavior is the same.
I've also tried to configure my mocked bean using this code:
#TestConfiguration
public class RestTemplateTestConfiguration {
#Bean("applicationDao")
#Primary
public static ApplicationDao mockApplicationDao() {
ApplicationDao mock = Mockito.mock(ApplicationDao.class);
Application testApplication = new Application();
testApplication.setName("test-application");
List<Application> allowedApplications = new ArrayList<Application>();
allowedApplications.add(testApplication);
Mockito
.when(mock.findAll())
.thenReturn(allowedApplications);
return mock;
}
}
However, it doesn't works right.
Application class is:
public class Application {
private String id;
//setters & getters
}
Any ideas?
First things first - the type of test. Answer: Unit test.
You are starting Spring context that manages a lifecycle of AuthorizationService and then you are trying to inject mock. What really happens is that Spring IoC container is injecting a real ApplicationDao (the one managed by Spring IoC container) into the AuthorizationService.
Solution:
Manage lifecyle of AuthorizationService by your test runner (like MockitoJUnitRunner and inject ApplicationDao mock into it):
#RunWith(MockitoJUnitRunner.class)
public class GroupReferencesTest {
private #InjectMocks AuthorizationService authorizationService;
private #Mock ApplicationDao applicationDao;
#Before
public void setUp() {
Application testApplication = new Application();
testApplication.setName("test-application");
List<Application> allowedApplications = new ArrayList<Application>();
allowedApplications.add(testApplication);
Mockito
.when(this.applicationDao.findAll())
.thenReturn(allowedApplications);
}
#Test
public void test() {
Application app = new Application();
app.getId("test-application");
assertTrue(this.authorizationService.isAuthorized(app));
}
}
Working example
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {AuthorizationService.class})
public class GroupReferencesTest {
#Autowired
private AuthorizationService;
#MockBean
private ApplicationDao applicationDao;
#Test
public void test() {
//given
Mockito.when(applicationDao.findAll()).thenReturn(emptyList());
//when & then
assertTrue(authorizationService.isAuthorized(app));
}
}

How to make data repository available in spring boot unit tests?

I'm consistently getting NPE on the repository I'm trying to implement.
Here's the repo:
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
Employee findByEmployeeId(String employeeId);
}
I'm just trying to do a simple integration test to make sure the app is wired correctly:
public class EmployeeRepositoryTest extends BaseIntegrationTest {
private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeRepositoryTest.class);
#Autowired
private static EmployeeRepository repo;
#Test
public void findByEmployeeIdReturnsAppropriateEmployee() {
Employee e = new Employee("Some", "Person", "0001111");
repo.save(e);
assertEquals("Did not find appropriate Employee", e, repo.findByEmployeeId("0001111"));
}
}
BaseIntegrationTest is just a collection of annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#ActiveProfiles("test")
#IntegrationTest("server.port:0")
public class BaseIntegrationTest {
#Test
public void contextLoads() {
}
}
Can I provide any more helpful information? Thanks.
Remove the keyword static from your repo field. Static fields aren't autowired.

Resources