모의 클라이언트를 사용하여 테스트 작성

단위 테스트를 위해 모의 객체를 삽입하도록 실제 클라이언트 구현을 스텁하는 방법을 알아봅니다. Rust용 Google Cloud 클라이언트 라이브러리와 함께 모의 클라이언트를 사용하면 네트워크 호출을 하거나 청구 요금이 발생하지 않는 제어되고 안정적인 단위 테스트를 작성할 수 있습니다.

종속 항목

Rust에는 여러 모의 객체 프레임워크가 있습니다. 이 가이드에서는 mockall을 사용합니다. 개발 종속 항목으로 추가합니다.

cargo add --dev mockall

또한 이 가이드에서는 Speech 클라이언트를 사용하여 예를 더 쉽게 따라할 수 있도록 합니다 (하지만 이러한 개념은 모든 클라이언트에 적용됨).

필요한 종속 항목을 Cargo.toml 파일에 추가합니다.

cargo add google-cloud-speech-v2 google-cloud-lro

클라이언트 모의 객체

모의 클라이언트로 코드를 테스트하려면 모의 객체 구조체를 정의하고 테스트 시나리오에 맞게 예상되는 동작을 구성한 후 해당 모의 객체를 애플리케이션 로직에 삽입합니다. 다음 예는 이 워크플로를 보여줍니다.

먼저 use 문을 추가하여 코드를 간소화합니다.

use google_cloud_gax as gax;
use google_cloud_speech_v2 as speech;

애플리케이션에 Speech 클라이언트를 사용하여 GetRecognizer를 호출하고 요청의 name 필드를 설정하며 서버 응답을 처리하는 함수가 있다고 가정합니다.

// An example application function.
//
// It makes an RPC, setting some field. In this case, it is the `GetRecognizer`
// RPC, setting the name field.
//
// It processes the response from the server. In this case, it extracts the
// display name of the recognizer.
async fn my_application_function(client: &speech::client::Speech) -> gax::Result<String> {
    client
        .get_recognizer()
        .set_name("invalid-test-recognizer")
        .send()
        .await
        .map(|r| r.display_name)
}

애플리케이션이 서비스의 다양한 응답을 처리하는 방법을 테스트할 수 있습니다.

다음으로 모의 객체 구조체를 정의합니다. 이 구조체는 speech::stub::Speech 특성을 구현합니다.

mockall::mock! {
    #[derive(Debug)]
    Speech {}
    impl speech::stub::Speech for Speech {
        async fn get_recognizer(&self, req: speech::model::GetRecognizerRequest, _options: gax::options::RequestOptions) -> gax::Result<gax::response::Response<speech::model::Recognizer>>;
    }
}

모의 객체의 인스턴스를 만듭니다. mockall::mock! 매크로는 이전에 정의된 구조체의 이름 앞에 Mock 프리픽스를 추가합니다.

let mut mock = MockSpeech::new();

모의 객체에 대한 기대치를 설정합니다. 예를 들어 코드가 특정 이름으로 GetRecognizer를 호출하고 서비스의 성공적인 응답을 시뮬레이션하도록 예상합니다.

mock.expect_get_recognizer()
    .withf(move |r, _|
        // Optionally, verify fields in the request.
        r.name == "invalid-test-recognizer")
    .return_once(|_, _| {
        Ok(gax::response::Response::from(
            speech::model::Recognizer::new().set_display_name("test-display-name"),
        ))
    });

모의 객체를 사용하여 Speech 클라이언트를 만듭니다.

let client = speech::client::Speech::from_stub(mock);

함수 호출

let display_name = my_application_function(&client).await?;

결과 확인:

assert_eq!(display_name, "test-display-name");

오류 시뮬레이션

오류 시뮬레이션은 성공 시뮬레이션과 비슷합니다. 오류를 시뮬레이션하려면 모의 객체에서 반환된 결과를 수정합니다.

mock.expect_get_recognizer().return_once(|_, _| {
    // This time, return an error.
    use gax::error::Error;
    use gax::error::rpc::{Code, Status};
    let status = Status::default()
        .set_code(Code::NotFound)
        .set_message("Resource not found");
    Err(Error::service(status))
});

from_stub()로 빌드된 클라이언트에는 내부 재시도 루프가 없습니다. 스텁의 모든 오류를 애플리케이션에 직접 반환합니다.

다음 단계

이 가이드의 전체 코드를 보려면 GitHub의 google-cloud-rust 저장소에서 소스 파일을 확인하세요.