【问题标题】:Spring Boot: How to test a class which is using gson object using autowiringSpring Boot:如何使用自动装配测试使用 gson 对象的类
【发布时间】:2021-07-02 12:15:00
【问题描述】:

我是 JUnit 和 Java 单元测试的新手。我在测试我的代码时遇到问题。任何帮助表示赞赏。

我的java类: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);
    }
}

我的测试班: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());
    }
}

这给了 NullPointerException 因为gson 对象没有被初始化。我们也不能模拟gson,因为Gson 类是final

如何测试此代码。我正在使用 spring bootjunit5.

【问题讨论】:

  • 那是因为您没有在测试中使用 Spring。将您的类转换为使用构造函数注入而不是字段注入,问题将很容易解决。

标签: java spring-boot mockito gson junit5


【解决方案1】:

更好的可测试性方法是将Gson 对象传递给服务的构造函数(即constructor dependency injection):

private ServiceB serviceB;

private Gson gson;

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

Spring 仍会像往常一样使用 GsonAutoConfiguration 配置类注入 Gson 对象。但是,在您的测试中,您现在可以使用常规的 Gson 对象构造 AService

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

注意:我使用 new GsonBuilder().create() 创建了 Gson 对象,因为这是 GsonAutoConfiguration 在生产中注入它所做的。但是您也应该能够使用简单的new Gson() 来创建它:

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

【讨论】:

  • 请注意,如果类只有一个构造函数,则不需要@Autowired
【解决方案2】:

我不建议模拟 Gson,而是使用 RefelectionUtils 创建和设置 Gson 对象并模拟其他依赖服务

@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());
  }
}

【讨论】:

  • 第一种方法不起作用,因为它会给 org.mockito.exceptions.base.MockitoException: Cannot mock/spy class com.google.gson.Gson Mockito cannot mock/spy because : - final class
  • 哎呀我错过了,但更新了答案,应该可以@RishabhSairawat
猜你喜欢
  • 2015-03-20
  • 2020-06-22
  • 2015-09-11
  • 2021-12-23
  • 2016-03-29
  • 2020-03-24
  • 2014-07-30
  • 1970-01-01
  • 2018-02-15
相关资源
最近更新 更多