「Build Type ‘debug’ contains custom BuildConfig fields」エラーの対策

問題

Android Studioでアプリをビルドすると、以下のようなエラーが発生しました。

Build Type 'debug' contains custom BuildConfig fields, but the feature is disabled.
To enable the feature, add the following to your module-level build.gradle:
android.buildFeatures.buildConfig true

このエラーは、build.gradle 内でBuildConfigにカスタムフィールドを追加しようとした際に、buildConfig機能が無効になっているために発生します。

このエラーの原因と解決方法を解説します。

エラーの原因

Android Gradle Plugin (AGP) 8 以降では、buildConfig機能がデフォルトで無効になっています。
つまり、カスタムBuildConfigフィールドを使用すると、エラーが発生します。

例えば、以下のようにbuild.gradle (Module: app)にbuildConfigFieldを追加している場合、このエラーが発生します。

android {
    buildTypes {
        debug {
            buildConfigField "String", "API_URL", "\"https://api.example.com\""
        }
    }
}

このエラーを解決するためには、buildConfig機能を有効にする必要があります。

解決策

1. buildConfigを有効にする

build.gradle (Module: app)を開き、以下の設定を追加してください。

android {
    buildFeatures {
        buildConfig true
    }
}

2. Gradle Syncを実行

設定を追加した後、Android Studioの「Sync Project with Gradle Files」を実行し、build.gradleの変更を反映します。

3. プロジェクトをリビルド

次に、プロジェクトをリビルドします。

  • メニューから Build → Rebuild Project を実行
  • または、ターミナルで以下のコマンドを実行
    ./gradlew clean
    ./gradlew build
    

これでエラーが解消されました。

LaravelでStorageのtemporaryUrlをモック化する方法

Laravelを使用していると、S3ストレージのtemporaryUrlメソッドを利用する場面が出てきます。

しかし、ユニットテスト環境では実際のS3にアクセスするのではなく、このtemporaryUrlをモック化してテストを行いたい場合があります。

本記事では、LaravelのStorageファサードを使用してtemporaryUrlをモック化する方法をご紹介します。

動機

通常、StoragetemporaryUrlは指定したファイルに対する一時的なアクセスURLを生成します。

しかし、ユニットテストでは外部サービス(この場合はAWS S3)に依存することなくテストを完結させたいものです。

そのため、temporaryUrlメソッドをモック化し、意図した値を返すように設定する必要があります。

モック化の手順

以下のコードスニペットは、Storageファサードをモック化し、temporaryUrlメソッドが指定したURLを返すように設定する方法を示しています。

Storage::shouldReceive('disk')
        ->with('s3')
        ->andReturnSelf();

Storage::shouldReceive('temporaryUrl')
        ->with('example.jpg', Mockery::type(\DateTimeInterface::class))
        ->andReturn('https://example.com/temp-url/example.jpg');

解説

  1. Storage::shouldReceive('disk')->with('s3')->andReturnSelf();
    Storage::disk('s3')が呼び出されたときに、Storageのモックインスタンス自身を返します。これにより、チェーンメソッドを使用する際にモックを適切に動作させることができます。

  2. Storage::shouldReceive('temporaryUrl')
    temporaryUrlが呼び出されたときに、指定したURLを返すように設定します。引数としてファイル名(example.jpg)とDateTimeInterface型のインスタンスが期待されます。

モック化を活用したテスト例

以下は、StoragetemporaryUrlをモック化し、ユニットテストで利用する例です。

public function testTemporaryUrl()
{
    // モック設定
    Storage::shouldReceive('disk')
        ->with('s3')
        ->andReturnSelf();

    Storage::shouldReceive('temporaryUrl')
        ->with('example1.jpg', Mockery::type(DateTimeInterface::class))
        ->andReturn('https://example.com/temp-url/example1.jpg');

    Storage::shouldReceive('temporaryUrl')
        ->with('example2.jpg', Mockery::type(DateTimeInterface::class))
        ->andReturn('https://example.com/temp-url/example2.jpg');

    // テスト: モック化されたURLの確認
    $url = Storage::disk('s3')->temporaryUrl('example1.jpg', now()->addMinutes(5));
    $this->assertEquals('https://example.com/temp-url/example1.jpg', $url);

    $url = Storage::disk('s3')->temporaryUrl('example2.jpg', now()->addMinutes(5));
    $this->assertEquals('https://example.com/temp-url/example2.jpg', $url);
}

テストのポイント

  • モック化により、実際にAWS S3に接続することなくテストを実行できます。
  • ファイル名や日付の引数ごとに返されるURLを自由に設定可能です。
  • テストの結果を保証するため、モック化したURLをassertEqualsで検証します。

まとめ

Laravelのユニットテストで外部ストレージの依存を排除することは、テストの信頼性とスピードを向上させます。

今回紹介した方法を活用すれば、簡単にtemporaryUrlメソッドをモック化でき、ストレージ関連のコードを効率よくテストできるようになります。

pod installでArgumentErrorになったときの対処法

pod installでArgumentErrorになったときの対処法

問題

pod install を実行した際に、以下のエラーが発生しました。

ArgumentError - [Xcodeproj] Unable to find compatibility version string for object version `70`.

このエラーは、CocoaPodsがプロジェクトのフォーマットバージョンを認識できない場合に発生します。

Xcodeのバージョンアップによりプロジェクト設定が変更されたため、古い設定のままでは pod install が正常に動作しません。

解決策

  • Xcodeでプロジェクトを開く
  • プロジェクトナビゲーターでプロジェクトファイル(青いアイコン)を選択します。
  • 右側のユーティリティペインを開きます。
  • 最初のタブでProject Formatのドロップダウンメニューが表示されます。
  • Project Formatを「Xcode 16.0」にする

Project Formatを最新のXcodeのバージョンに合わせることで、CocoaPodsが適切にプロジェクトを認識できるようになります。

参考

Laravelで`laravelcollective/html`の`selectRange`を`spatie/laravel-html`で再現する方法

はじめに

Laravelでlaravelcollective/htmlからspatie/laravel-htmlに移行する際、laravelcollective/htmlの便利なselectRangeメソッドが使えないことに気づきました。本記事では、spatie/laravel-htmlで同様の機能を再現する方法について説明します。

laravelcollective/htmlのselectRange

laravelcollective/htmlパッケージは、特定の範囲(例えば、年)を選択できるセレクトボックスを簡単に生成するselectRangeメソッドを提供しています。このメソッドを使うことで、指定した範囲の選択肢を生成し、デフォルト値を設定することもできます。

{!! Form::selectRange('year', $fromYear, $toYear, $year) !!}

上記のコードは、$fromYearから$toYearまでの年をセレクトボックスの選択肢として生成し、デフォルト値として$yearを設定します。

spatie/laravel-htmlでのselectRangeの再現方法

spatie/laravel-htmlには、selectRangeに相当するメソッドが用意されていないため、範囲の選択肢を手動で生成する必要があります。このセクションでは、range関数とarray_combine関数を使って同等の機能を実装する方法を紹介します。

まず、range関数で年の範囲を配列として生成し、array_combine関数を使って、キーと値が同じになるように配列を整えます。

@php
    $years = range($fromYear, $toYear);
@endphp

{!! html()->select('year', array_combine($years, $years), $year) !!}

このコードは、$fromYearから$toYearまでの年を生成し、その配列をselectメソッドのオプションとして渡します。また、$yearをデフォルトの選択肢として設定しています。

これにより、laravelcollective/htmlのselectRangeと同様の機能を、spatie/laravel-htmlを使って実現できます。