1. 概要

このチュートリアルでは、依存性注入を使用して、単体テストのためにMockitoモックをSpringBeanに挿入する方法について説明します。

コンポーネントが外部システムへのアクセスに依存することが多い実際のアプリケーションでは、適切なテスト分離を提供することが重要です。これにより、各テストのクラス階層全体を関与させることなく、特定のユニットの機能のテストに集中できます。

モックを注入することは、そのような分離を導入するためのクリーンな方法です。

2. Mavenの依存関係

単体テストとモックオブジェクトには、次のMaven依存関係が必要です。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.6.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.6.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.21.0</version>
</dependency>

この例ではSpringBootを使用することにしましたが、従来のSpringでも問題なく動作します。

3. テストを書く

3.1. ビジネスロジック

まず、テストする簡単なサービスを作成しましょう。

@Service
public class NameService {
    public String getUserName(String id) {
        return "Real user name";
    }
}

次に、それをUserServiceクラスに挿入します。

@Service
public class UserService {

    private NameService nameService;

    @Autowired
    public UserService(NameService nameService) {
        this.nameService = nameService;
    }

    public String getUserName(String id) {
        return nameService.getUserName(id);
    }
}

この記事では、指定されたクラスは、指定されたIDに関係なく単一の名前を返します。 これは、複雑なロジックをテストすることに気を取られないようにするために行われます。

Beanをスキャンしてアプリケーションを初期化するには、標準のSpring Bootメインクラスも必要です。

@SpringBootApplication
public class MocksApplication {
    public static void main(String[] args) {
        SpringApplication.run(MocksApplication.class, args);
    }
}

3.2. テスト

それでは、テストロジックに移りましょう。 まず、テストのアプリケーションコンテキストを構成する必要があります。

@Profile("test")
@Configuration
public class NameServiceTestConfiguration {
    @Bean
    @Primary
    public NameService nameService() {
        return Mockito.mock(NameService.class);
    }
}

@Profile アノテーションは、「テスト」プロファイルがアクティブな場合にのみこの構成を適用するようにSpringに指示します。 @Primary アノテーションは、このインスタンスが実際のインスタンスの代わりに自動配線に使用されることを確認するためにあります。 メソッド自体が、NameServiceクラスのMockitoモックを作成して返します。

これで、単体テストを作成できます。

@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MocksApplication.class)
public class UserServiceUnitTest {

    @Autowired
    private UserService userService;

    @Autowired
    private NameService nameService;

    @Test
    public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() {
        Mockito.when(nameService.getUserName("SomeId")).thenReturn("Mock user name");
        String testName = userService.getUserName("SomeId");
        Assert.assertEquals("Mock user name", testName);
    }
}

@ActiveProfiles アノテーションを使用して、「テスト」プロファイルを有効にし、前に作成したモック構成をアクティブにします。 その結果、Springは UserService クラスの実際のインスタンスを自動配線しますが、NameServiceクラスのモックです。 テスト自体は、かなり典型的なJUnit+Mockitoテストです。 モックの目的の動作を構成してから、テストするメソッドを呼び出し、期待する値を返すことを表明します。

このようなテストで環境プロファイルを使用しないようにすることも可能です(推奨されませんが)。 これを行うには、@Profileおよび@ActiveProfilesアノテーションを削除し、 @ContextConfiguration(classes = NameServiceTestConfiguration.class)アノテーションをに追加します。 UserServiceTestクラス。

4. 結論

この短い記事では、MockitoモックをSpringBeanに注入するのがいかに簡単かを学びました。

いつものように、すべてのコードサンプルはGitHubで入手できます。