[英]@Autowired field null when executing production code via integration tests
在過去的幾天里,我一直在摸不着頭腦,有點奇怪。 我有一個 JPA 存儲庫,它被現場注入到服務 class 中。在運行服務器並通過客戶端發送請求時工作完美,但是當通過集成測試執行代碼時,注入的字段 class (CustomerRepository) 始終是 null。
我已經通過 inte.net 嘗試了各種建議,但我沒有找到與我類似的情況,任何幫助將不勝感激
客服 class
@GRpcService
public class CustomerService extends CustomerServiceGrpc.CustomerServiceImplBase {
@Autowired
private CustomerRepository repository;
@Override
public void createCustomer(CreateCustomerRequest request, StreamObserver<CreateCustomerResponse> responseObserver) {
final CustomerDao convertedDao = ProtoToDaoConverter.convertCustomerRequestProtoToCustomerDao(request);
repository.save(convertedDao);
responseObserver.onNext(CreateCustomerResponse.newBuilder().setSuccess(true).build());
responseObserver.onCompleted();
}
}
集成測試
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class CustomerServiceIT {
@Rule
private final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
@Test
public void something() throws IOException {
String serverName = InProcessServerBuilder.generateName();
// Create a server, add service, start, and register for automatic graceful shutdown.
grpcCleanup.register(InProcessServerBuilder
.forName(serverName).directExecutor().addService(new CustomerService()).build().start());
customerServiceGrpc.CustomerServiceBlockingStub blockingStub = CustomerServiceGrpc.newBlockingStub(
// Create a client channel and register for automatic graceful shutdown.
grpcCleanup.register(InProcessChannelBuilder.forName(serverName).directExecutor().build()));
final CreateCustomerRequest request = CreateCustomerRequest.newBuilder().setFirstName("Simon").setSecondName("Brown").setRole("Product Developer").build();
final CreateCustomerResponse response = blockingStub.createCustomer(request);
}
}
您可以使用Mockito或任何其他測試框架來模擬您的 class 依賴項(您的服務和您的 JPA 存儲庫)。
您可以使用這些功能:
@InjectMocks
- 實例化測試 object 實例,並嘗試將用@Mock
或@Spy
注釋的字段注入到測試 object 的私有字段中@Mock
- 創建它注釋的字段的模擬實例在您的測試 class 中,您必須使用@Mock
來注入“假存儲庫”:
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class CustomerServiceTest {
@InjectMocks
private CustomerService testingObject;
@Mock
private CustomerRepository customRepository;
@Rule
private final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
@BeforeMethod
public void initMocks(){
MockitoAnnotations.initMocks(this);
}
@Test
public void something() throws IOException {
// inside the testing method you have to define what you mocked object should return.
// it means mocking the CustomRepository methods
CustomerDao customer = new CustomerDao(); // fill it with data
Mockito.when(customRepository.save()).thenReturn(customer);
// Create a server, add service, start, and register for automatic graceful shutdown.
grpcCleanup.register(InProcessServerBuilder
.forName(serverName).directExecutor().addService(new CustomerService()).build().start());
customerServiceGrpc.CustomerServiceBlockingStub blockingStub = CustomerServiceGrpc.newBlockingStub(
// Create a client channel and register for automatic graceful shutdown.
grpcCleanup.register(InProcessChannelBuilder.forName(serverName).directExecutor().build()));
final CreateCustomerRequest request = CreateCustomerRequest.newBuilder().setFirstName("Simon").setSecondName("Brown").setRole("Product Developer").build();
final CreateCustomerResponse response = blockingStub.createCustomer(request);
}
}
由於您的存儲庫及其方法是模擬的,因此您的 customerService 應該填充虛假數據以用於測試目的。
注意:很高興有一個類的命名約定,尤其是測試類。 一個常見的用法是總是像我在答案中所做的那樣給出 xxTest 的后綴
如果無法閱讀堆棧跟蹤,就很難回答。 我會通過查看 spring 上下文配置類來開始調查這個問題。 也許其中一些在集成測試的運行時丟失了。
如果您的應用程序中存在 spring @Configuration
或其他@Component
類,則可能有助於在您的測試中顯式加載它們,以及意外的空值CustomerRepository
:
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {AppConfig.class, CustomerRepository.class })
public class CustomerServiceIT {
這可能無法解決問題,但可能會揭示一些有助於您調查問題的錯誤消息。
在測試中,您調用new CustomerService()
。 您自己創建一個 object,而不是通過 spring。我想您應該在測試 class 中創建一個字段
@Autowired private final CustomerService customerService
並將其傳遞給grpcCleanup.register(InProcessServerBuilder.forName(serverName).directExecutor().addService(customerService).build().start());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.