🦔

Rustで𝕏(Twitter)APIをもっとモックする。

2024/06/19に公開

目的

以前Rustで𝕏(Twitter)APIをモックするという記事を書きました。
この後ライブラリの仕様を変更して、環境変数で向き先を変えるだけで無く、引数でも向き先を変えられるようにしました。

それにより、引数で向き先を変える方法は単体テスト向きに使えて、環境変数で向き先を変える方法はシステムテストやE2Eテストで使えそうでとわかりました。

今回のコードはaoyagikouhei/mock_x_sampleに置いてあります。

コード

Rust

Cargo.toml
[package]
name = "sample"
version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = "1"
mockito = "1.4"
serde_json = "1"
twapi-v2 = { version = "0.15", default-features = false, features = ["rustls-tls", "oauth10a"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync"] }
main.rs
use mockito::{Mock, Server, ServerGuard};
use serde_json::json;
use twapi_v2::{api::{get_2_users_me, TwapiOptions}, oauth10a::OAuthAuthentication};

async fn execute_x(twapi_options: Option<TwapiOptions>) -> anyhow::Result<()> {
    let auth = OAuthAuthentication::new(
        std::env::var("CONSUMER_KEY").unwrap_or_default(),
        std::env::var("CONSUMER_SECRET").unwrap_or_default(),
        std::env::var("ACCESS_KEY").unwrap_or_default(),
        std::env::var("ACCESS_SECRET").unwrap_or_default(),
    );
    let mut api = get_2_users_me::Api::new();
    if let Some(twapi_options) = twapi_options {
        api = api.twapi_options(twapi_options);
    }
    match api.execute(&auth).await 
    {
        Ok((response, _rate_limit)) => {
            println!("{:?}", response);
            Ok(())
        }
        Err(err) => Err(err.into()),
    }
}

async fn make_mock() -> (ServerGuard, Mock) {
    let mut server = Server::new_async().await;
    let json = json!({
        "data": {
            "id": "123",
            "name": "モック",
            "username": "mock",
        }
    });
    let mock = server
        .mock("GET", "/2/users/me")
        .match_query(mockito::Matcher::Any)
        .with_status(200)
        .with_header("content-type", "application/json")
        .with_body(json.to_string())
        .create_async()
        .await;
    (server, mock)
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // モック無し
    let _ = execute_x(None).await?;

    // モックあり
    let (server, mock) = make_mock().await;
    let twapi_options = Some(TwapiOptions {
        prefix_url: Some(server.url()),
        ..Default::default()
    });
    let _ = execute_x(twapi_options).await?;
    mock.assert();
    Ok(())
}

execute_xでOAuth認証している自分自身の情報が取得できます。
引数のTwapiOptionsは向き先を変えるデータになります。

make_mockは自分自身の情報を取得するAPIのモックになります。

mainではモック無しとモックありで実行しています。
実行結果は以下の通りです。

cargo run
Response { data: Some(Users { connection_status: None, created_at: None, description: None, entities: None, id: "19522946", location: None, most_recent_tweet_id: None, name: "青柳康平", pinned_tweet_id: None, profile_image_url: None, protected: None, public_metrics: None, url: None, username: "aoyagikouhei", verified: None, verified_type: None, withheld: None, extra: {} }), errors: None, includes: None, extra: {} }
Response { data: Some(Users { connection_status: None, created_at: None, description: None, entities: None, id: "123", location: None, most_recent_tweet_id: None, name: "モック", pinned_tweet_id: None, profile_image_url: None, protected: None, public_metrics: None, url: None, username: "mock", verified: None, verified_type: None, withheld: None, extra: {} }), errors: None, includes: None, extra: {} }

TypeScript

先ほどは本当のAPIを叩いていましたが、次に外部にモックサーバーを立てて実行してみます。
honoフレームワークを利用しました。

index.ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/2/users/me', (c) => {
  return c.json({data: {id: '999', name: '予定表~①💖ハンカクだ', username: 'yoteihyo'}})
})

export default app

npm run devでlocalhost:3000で起動します。
この状態でRustを以下のように起動します。

TWAPI_V2_TWITTER_API_PREFIX_API=http://localhost:3000 cargo run
Response { data: Some(Users { connection_status: None, created_at: None, description: None, entities: None, id: "999", location: None, most_recent_tweet_id: None, name: "予定表~①💖ハンカクだ", pinned_tweet_id: None, profile_image_url: None, protected: None, public_metrics: None, url: None, username: "yoteihyo", verified: None, verified_type: None, withheld: None, extra: {} }), errors: None, includes: None, extra: {} }
Response { data: Some(Users { connection_status: None, created_at: None, description: None, entities: None, id: "123", location: None, most_recent_tweet_id: None, name: "モック", pinned_tweet_id: None, profile_image_url: None, protected: None, public_metrics: None, url: None, username: "mock", verified: None, verified_type: None, withheld: None, extra: {} }), errors: None, includes: None, extra: {} }

Rustのコードを一切変更せずに環境変数だけで向き先がかわりました。
引数で向き先を変更すると環境変数よりも優先して利用されます。

まとめ

引数と環境変数で𝕏APIをモックしました。
引数による向き先の変更は単体テストなどで向き先を変更できて便利です。
環境変数はアプリケーションとしてプログラムを動かしても向き先を変えられるので、システムテストやE2Eテストなどで利用できると思います。

Discussion