简体   繁体   中英

Spring Boot: How to test a class which is using gson object using autowiring

I am new to JUnit and unit testing in java. I am having an issue while testing my code. Any help is appreciated.

My java class: AService.java

@Service
public class AService {

    @Autowired
    private ServiceB serviceB;

    @Autowired
    private Gson gson;

    public MyEntity getEntity() {
        String jsonResponse = serviceB.getResponse();
        return gson.fromJson(jsonResponse, MyEntity.class);
    }
}

My test class: AServiceTest.java

@ExtendWith(MockitoExtension.class)
public class AServiceTest {

    @Mock
    private ServiceB serviceB;

    @Autowired
    private Gson gson;

    @InjectMocks
    private AService aService;

    @Test
    public void getEntityTest() {
        String serviceBResponse = "{\"id\":55,\"name\":\"My entity\",\"address\":\"XYZ\"}";
        when(serviceB.getResponse()).thenReturn(serviceBResponse);

        MyEntity entity = aService.getEntity();
        assertEquals("My entity", entity.getName());
    }
}

This is giving NullPointerException because gson object is not getting initialized. Also we can not mock gson as Gson class is final .

How can I test this code. I am using spring boot and junit5.

A better way for testability is to have the Gson object passed to a constructor of the service (ie constructor dependency injection ):

private ServiceB serviceB;

private Gson gson;

@Autowired
AService(ServiceB serviceB, Gson gson) {
    this.serviceB = serviceB;
    this.gson = gson;
}

Spring would still inject the Gson object as normal using the GsonAutoConfiguration configuration class. In your test, however, you can now construct the AService using a regular Gson object:

AService aService = new AService(serviceB, new GsonBuilder().create());

Note: I've used new GsonBuilder().create() to create the Gson object because this is what GsonAutoConfiguration does to inject it in production. But you should also be able to create it using simply new Gson() :

AService aService = new AService(serviceB, new Gson());

I wouldn't recommend mocking Gson instead of that you can create and set the Gson object using RefelectionUtils and mock other dependency services

@ExtendWith(MockitoExtension.class)
public class AServiceTest {

   private ServiceB serviceB = Mocktio.mock(ServiceB.class);

   private Gson gson = new GsonBuilder().create();

  
   private AService aService = new AService();

   @Before
   public void setup() {
     ReflectionTestUtils.setField(aService, "serviceB", serviceB);
     ReflectionTestUtils.setField(aService, "gson", gson);
  }

   @Test
   public void getEntityTest() {
    String serviceBResponse = "{\"id\":55,\"name\":\"My entity\",\"address\":\"XYZ\"}";

    when(serviceB.getResponse()).thenReturn(serviceBResponse);
  
    MyEntity entity = aService.getEntity();
    assertEquals("My entity", entity.getName());
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM