Skip to content

Unable to resolve NoSuchElementException while unit testing

I am trying to test supplierService class and getting NoSuchElementException while testing getSKUNameTest()

java.util.NoSuchElementException: No value present
    at java.util.Optional.get(Optional.java:135)
    at com.inventory.SpringInventory1ApplicationTests.getSKUNameTest(SpringInventory1ApplicationTests.java:66)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)



Catalog.java and Supplier.java are the entity class

Catalog.java

package com.inventory.entities;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;

@Entity
@Table(name = "catalog")
public class Catalog {

    @Id
    @Column(length = 50)
    // @GeneratedValue
    private int skuCode;
    @Column(length = 50)
    private String skuName;
    @Column(length = 50)
    private String skuDesc;
    @Column(length = 50)
    private String bName;
    @Column(length = 50)
    private String bDesc;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "supplier_id", nullable = false, unique = true)
    @JsonManagedReference
    @JsonIgnore
    private Supplier supplier;// FK

    public Catalog() {
    }

    public Catalog(int skuCode, String skuName, String skuDesc, String bName, String bDesc, Supplier supplier) {
        this.skuCode = skuCode;
        this.skuName = skuName;
        this.skuDesc = skuDesc;
        this.bName = bName;
        this.bDesc = bDesc;
        this.supplier = supplier;
    }

    public int getSkuCode() {
        return skuCode;
    }

    public void setSkuCode(int skuCode) {
        this.skuCode = skuCode;
    }

    public String getSkuName() {
        return skuName;
    }

    public void setSkuName(String skuName) {
        this.skuName = skuName;
    }

    public String getSkuDesc() {
        return skuDesc;
    }

    public void setSkuDesc(String skuDesc) {
        this.skuDesc = skuDesc;
    }

    public String getbName() {
        return bName;
    }

    public void setbName(String bName) {
        this.bName = bName;
    }

    public String getbDesc() {
        return bDesc;
    }

    public void setbDesc(String bDesc) {
        this.bDesc = bDesc;
    }

    public Supplier getSupplier() {
        return supplier;
    }

    public void setSupplier(Supplier supplier) {
        this.supplier = supplier;
    }

    @Override
    public String toString() {
        return "Catalog [skuCode=" + skuCode + ", skuName=" + skuName + ", skuDesc=" + skuDesc + ", bName=" + bName
                + ", bDesc=" + bDesc + ", supplier=" + supplier + "]";
    }

}


Supplier.java

package com.inventory.entities;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

import com.fasterxml.jackson.annotation.JsonBackReference;

@Entity
@Table(name = "supplier")
public class Supplier {

    @Id
    @Column(length = 50)
    private int supplierId;
    @Column(length = 50)
    private String supplierName;
    @OneToOne(mappedBy = "supplier",fetch = FetchType.LAZY)
    @JsonBackReference
    private Catalog catalog;

    public Supplier() {
    }

    public Supplier(int supplierId, String supplierName) {
        super();
        this.supplierId = supplierId;
        this.supplierName = supplierName;
    }

    public int getSupplierId() {
        return supplierId;
    }

    public void setSupplierId(int supplierId) {
        this.supplierId = supplierId;
    }

    public String getSupplierName() {
        return supplierName;
    }

    public void setSupplierName(String supplierName) {
        this.supplierName = supplierName;
    }

    public Catalog getCatalog() {
        return catalog;
    }

    public void setCatalog(Catalog catalog) {
        this.catalog = catalog;
    }

    @Override
    public String toString() {
        return "Supplier [supplierId=" + supplierId + ", supplierName=" + supplierName + ", catalog=" + catalog + "]";
    }

}


Service Classes

CatalogService.java

package com.inventory.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.inventory.entities.Catalog;
import com.inventory.repository.CatalogRepository;

@Service
public class CatalogService {
    
    @Autowired
    private CatalogRepository catalogRepository;
    
    public Catalog getCatalogById(int id) {
        return catalogRepository.findById(id).get();
    }
    
    public Catalog saveCatalog(Catalog catalog) {
        return catalogRepository.save(catalog);
    }
    
}


SupplierService.java

package com.inventory.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.inventory.entities.Supplier;
import com.inventory.repository.SupplierRepository;

@Service
public class SupplierService {
    
    @Autowired
    private SupplierRepository supplierRepository;

    public Supplier getSupplierById(int id) {
        return supplierRepository.findById(id).get();
    }
    
    public Supplier insertSupplier(Supplier supplier) {
        return supplierRepository.save(supplier);
    }
    

}


Repository Classes

SupplierRepository.java

package com.inventory.repository;

import org.springframework.data.repository.CrudRepository;

import com.inventory.entities.Supplier;

public interface SupplierRepository extends CrudRepository<Supplier, Integer>{

}


CatalogRepository.java

package com.inventory.repository;

import org.springframework.data.repository.CrudRepository;

import com.inventory.entities.Catalog;

public interface CatalogRepository extends CrudRepository<Catalog, Integer>{

}


Here is Testing Class

SpringInventory1ApplicationTests.java

package com.inventory;

import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

import java.util.Optional;

import org.junit.Before;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;

import com.inventory.entities.Catalog;
import com.inventory.entities.Supplier;
import com.inventory.repository.CatalogRepository;
import com.inventory.repository.SupplierRepository;
import com.inventory.service.CatalogService;
import com.inventory.service.SupplierService;

@RunWith(SpringRunner.class)
@SpringBootTest
class SpringInventory1ApplicationTests {

    @Autowired
    private CatalogService catalogSevice;
    @InjectMocks
    private SupplierService supplierService;
    
    @MockBean
    private CatalogRepository catalogRepository;
    
    @Mock
    private SupplierRepository supplierRepository;
    
    @Before
    void setUp() {
        MockitoAnnotations.initMocks(this);
    }
    
    @Test
    public void getCatalogByIdTest() {
        Catalog catalog = new Catalog(201,"Kitchen Products", "Daily Products", "bajaj", "bajaj Eletronics", new Supplier(1,"Shubham"));
        when(catalogRepository.findById(201)).thenReturn(Optional.of(catalog));
        assertEquals(catalog,catalogSevice.getCatalogById(201));
    }
    
    @Test
    public void getSKUNameTest() {
        Supplier supplier = new Supplier(1,"John");
        Catalog catalog = new Catalog();
        catalog.setbName("Bajaj");
        catalog.setbDesc("Eletrical gadgets");
        catalog.setSkuCode(101);
        catalog.setSkuName("Mixer");
        catalog.setSupplier(supplier);
        
        //supplier.setCatalog(catalog);     
        when(supplierRepository.findById(1).get()).thenReturn(supplier);
        Supplier s = supplierService.getSupplierById(1);
        assertEquals("Mixer",supplierService.getSupplierById(1).getCatalog().getSkuName());
    }

    
    @Test
    public void insetCatalogTest() {
        Catalog catalog = new Catalog(201,"Kitchen Products", "Daily Products", "bajaj", "bajaj Eletronics", new Supplier(6,"Shubham"));
        when(catalogRepository.save(catalog)).thenReturn(catalog);
        assertEquals(catalog, catalogSevice.saveCatalog(catalog));
    }
    
    
    @Test
    public void insertSupplierTest() {
        Supplier supplier = new Supplier(20, "Shubhanjali");
        when(supplierRepository.save(supplier)).thenReturn(supplier);
        assertEquals(supplier, supplierService.insertSupplier(supplier));
    }

}

I am getting NoSuchElementException in testing getSKUNameTest(). while debugging I noticed that when(supplierRepository.findById(1).get()).thenReturn(supplier); this line is returning nothing, but I don’t know how to resolve this issue, Please Help.

Please help me as I am new to Spring and Hibernate as well in stackoverflow if anything needs to be edited or question is not clear please guide me so I can improve it further.

Answer

You stub the call in the wrong way.

when(supplierRepository.findById(1).get()).thenReturn(supplier);

Refactor to:

when(supplierRepository.findById(1)).thenReturn(Optional.of(supplier));

When you have a chain of calls, you need to stub each consecutive call one by one (assuming all objects returned in the interim are mocks).

Here, I take advantage of the fact that Optional is a simple object which is easy to construct, there is no additional value of mocking it.

On top of that:

  • Test one object at a time. Here you test catalogSevice and supplierService. Separate these tests.
  • Your annotations are a mess. Both objects under test are initialized in a different way. Either use Mockito annotations (@Mock, @InjectMocks, MockitoAnnotations.initMocks or Mockito runner) or use Spring ones (@SpringBootTest, @MockBean, @Autowired). In particular, @Mock fields are not injected into your Spring context. In this case I advise going the former way – spring tests tend to create more beans and take longer to execute.