1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

アーキテクチャテストAdvent Calendar 2020

Day 8

ArchUnit 実践:ドメイン層で発生した例外は UI 層やアプリ層で捕捉しきる(大域例外ハンドラで捕捉しない)

Last updated at Posted at 2020-12-08
// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* Spring Boot 2.4.0
* JUnit 5.7.0
* ArchUnit 0.14.1

アーキテクチャテストのモチベーション

ドメイン固有の例外は、そのユースケースを制御する責務をもつコントローラーやアプリケーションサービスで捕捉し、適切な後処理を行うべき。

Spring Boot でいうと、@ExceptionHandler を付与したメソッド(大域例外ハンドラ)が、ドメイン層の例外を捕捉しないことを担保したい。

アーキテクチャテストの実装

package com.example;

import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.Test;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.List;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods;

class ArchitectureTest {

    // 検査対象のクラス
    private static final JavaClasses CLASSES =
            new ClassFileImporter()
                    .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
                    .importPackages("com.example");

    @Test
    void ドメイン層で発生した例外を大域例外ハンドラで捕捉しない() {
        methods().that().areAnnotatedWith(ExceptionHandler.class)
            .should()
            .notHaveRawParameterTypes(new DescribedPredicate<>("ドメイン層の例外クラス") {
                /**
                 * @param params `@ExceptionHandler` でアノテートされたメソッドの引数のリスト
                 * @return 引数にドメイン層の例外クラスを含む場合、true
                 */
                @Override
                public boolean apply(final List<JavaClass> params) {
                    JavaClass exceptionClass = params.stream()
                            .filter(clazz -> clazz.isAssignableTo(Exception.class))
                            .findFirst()
                            .orElseThrow();

                    return exceptionClass.getPackageName().startsWith("com.example.domain");
                }
            })
            .check(CLASSES);
    }
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?