Spring 引导:如何使用自动装配测试使用 gson 对象的 class

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

我是 java 中 JUnit 和单元测试的新手。我在测试代码时遇到问题。感谢您的帮助。

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

我的测试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 class 是 final.

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

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

private ServiceB serviceB;

private Gson gson;

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

Spring 仍会使用 GsonAutoConfiguration 配置 class 正常注入 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());

我不建议模拟 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());
  }
}