1. ホーム
  2. スプリング

SpringBootのテスト

2022-03-01 08:12:33

元記事のアドレスです。 https://www.jianshu.com/p/72b19e24a602

前文

<ブロッククオート

Macでのアイデアショートカット、command+shift+Tは、クラスに基づいてショートカットを生成します。

Springコンテナ内のクラスに対するユニットテストの実行

UserService クラスを src/main の下に作成し、単一のクラスとしてテストし、そのユニットテストクラスを生成し (command+shift+T のショートカットを使用)、テストクラスを src/test の下に生成します。

@Service
public class UserService {

    public Integer addUser(String username){
        System.out.println("user dao adduser [username="+username+"]");
        if(username == null){
            return 0;
        }
        return 1;
    }
}


springbootの起動クラスです。

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


テストクラスです。

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void addUser() throws Exception {
        Assert.assertEquals(Integer.valueOf(1),userService.addUser("zhihao.miao"));
        Assert.assertEquals(Integer.valueOf(0),userService.addUser(null));
    }

}


ブラインドスポットスキャン

RunWithアノテーション、SpringRunnerクラス、SpringJUnit4ClassRunnerクラス、SpringBootTestアノテーションを解説しています。

RunWithアノテーション

クラスが @RunWith でアノテーションされている場合、または @RunWith でアノテーションされたクラスを拡張している場合、JUnit は JUnit に組み込まれているランナーではなく、それが参照しているクラスを呼び出してそのクラス内のテストを実行するようにします。この機能は、開発の後半に追加されました。この機能は強力に思えますが、ランナー API がどのように変更されるかは、現在内部にあるいくつかのクラスが改良され、公開される可能性があります。
クラスが @RunWith でアノテーションされている場合、または @RunWith でアノテーションされたクラスを継承している場合、JUnit は開発者が junit 内部でテストを構築する代わりに、参照するクラスを呼び出してそのクラスでテストを実行するようにします。私たちはこの機能を開発プロセスで使用しています。

例えば、JUnit 4 のスイートは RunWith と Suite という名前のカスタム ランナーを使って構築されます。
例えば、スイートはRunWithアノテーションを使用して構築されます。

@RunWith(Suite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {
}


<イグ

SpringRunnerアノテーション

SpringRunnerは、SpringJUnit4ClassRunnerのエイリアスです。
SpringRunner SpringJUnit4ClassRunner のエイリアスです。

このクラスを使用するには、JUnit 4ベースのテストクラスに @RunWith(SpringRunner.class) のアノテーションを付けるだけです。
このクラスを使用するには、JUnit 4 に依存するテスト・クラスに @RunWith(SpringRunner.class) のアノテーションを付けるだけです。

以外のランナーでSpring TestContext Frameworkを使用したい場合は、以下のようになります。
これは、 org.springframework.test.context.junit4.rules.SpringClassRule を使用します。 SpringClassRule
と org.springframework.test.context.junit4.rules で構成されています。
これを使う代わりに Spring のテストコンテキストを使いたい場合は org.springframework.test.context.junit4.rules.SpringClassRule org.springframework.test.context.junit4.rules. .

SpringJUnit4ClassRunner

SpringJUnit4ClassRunnerはJUnitのカスタム拡張機能です。
BlockJUnit4ClassRunner の機能を提供します。
Spring TestContext Framework を標準の JUnit テストに適用するには
TestContextManager と関連するサポートクラスとアノテーションを提供します。
SpringJUnit4ClassRunnerはJUnitのBlockJUnit4ClassRunnerクラスの通常の拡張で、JUnitテストの仕様にいくつかの春のテスト環境のコンテキストを提供する、つまりTestContextManagerと関連するサポートクラスとアノテーションを意味します。

SpringBootTestのアノテーション

Spring Bootベースのテストを実行するテストクラスで指定できるアノテーションです。
通常のSpring TestContextに加え、以下の機能を提供します。
フレームワークです。
アノテーションは、Spring Boot環境を実行するテストクラスを定式化します。以下の機能の一部が提供されています。

特定のContextConfiguration#loader()@ContextConfiguration(loader=...)が定義されていない場合、SpringBootContextLoaderをデフォルトのContextLoaderとして使用します。
特定のContextConfiguration#loader() (@ContextConfiguration(loader=...))が定義されていない場合、SpringBootContextLoaderがデフォルトContextLoaderとして使用されることになります。

ネストされた @Configuration が使用されず、明示的な #classes() クラスがない場合、自動的に @SpringBootConfiguration が検索されます。
を指定しました。
SpringBootConfigurationのアノテーションを持つファイルを自動的に検索します。

properties() properties 属性} を使用して、カスタム環境プロパティを定義できるようにしました。
設定ファイルを読み込むための Environment クラスの自動インジェクションを許可します。

異なる #webEnvironment() webEnvironment モードへのサポートを提供します。
をリッスンしている完全に実行中のコンテナを起動する機能などがあります。
WebEnvironment#DEFINED_PORT が定義されているか、WebEnvironment#RANDOM_PORT が定義されています。
ランダムポート
ランダムなポートやカスタムポートを使用することを許可する機能を完全に備えた webEnvironment 環境を提供します。

org.springframework.boot.test.web.client.TestRestTemplate を登録する。
TestRestTemplate Bean は、完全に動作するコンテナを使用するウェブテストで使用します。
TestRestTemplateクラスは、インターフェイスの呼び出しに行くために登録されています。

Springbootのテスト手順

  • 以下の2つのアノテーションをテストクラスの上に直接追加します。
    @RunWith(SpringRunner.class)を使用します。
    SpringBootTest
    はspringのコンテナのインスタンスを取得し、@Autowiredが設定されていれば自動的にオブジェクトが注入されます。

テスト環境でBeanを取得し、プロジェクトでUserクラスを新規に作成し、テストモジュールでテストします。

src/main の下に新しいインスタンス User を作成します。

@Component
public class User {
}


src/test以下にテスト用のクラスを作成し、テストします。

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserTest {


    @Autowired
    public ApplicationContext context;

    @Test
    public void testNotNull(){
        Assert.assertNotNull(context.getBean(User.class));
    }
}


テスト環境でのみ有効なビーン

src/test の下に、それぞれ @TestComponent と @TestConfiguration のアノテーションで変更された、テスト環境でのみ有効な2つの新しいクラスが見つかりました。

@TestComponent
public class Cat {

    public void index(){
        System.out.println("cat index");
    }
}

@TestConfiguration
public class TestBeanConfiguration {

    @Bean
    public Runnable createRunnable(){
        return () -> System.out.println("=====createRunnable=======");
    }
}


@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TestBeanConfiguration.class,Cat.class})
public class TestApplication {

    @Autowired
    public ApplicationContext context;

    @Test
    public void testNotNull(){
        Runnable runnable = context.getBean(Runnable.class);
        runnable.run();
        System.out.println("--------");

        Cat cat = context.getBean(Cat.class);
        cat.index();
    }
}


テストクラスです。

@RunWith(SpringRunner.class)
@SpringBootTest
public class EnvTest {

    @Autowired
    public Environment environment;

    @Test
    public void testValue(){
        Assert.assertEquals("zhihao.miao",environment.getProperty("developer.name"));

    }
}


テスト環境のコンテナに特定のクラスを含めることを示すために、@SpringBootTestアノテーションのパラメータクラスにパラメータを追加する必要があります。

TestComponentアノテーション

TestConfigurationアノテーション

設定ファイルプロパティの読み込み

springbootは公式環境の設定ファイルではなく、src/test/resources以下の設定のみを読み込みます(以前の1.4.*ではテスト環境の設定ファイルを優先的に読み込み、その後公式環境の設定ファイルを読み込むという流れでした)。

@RunWith(SpringRunner.class)
@SpringBootTest(properties = {"app.version=1.0"})
public class EnvTest2 {

    @Autowired
    private ConfigurableEnvironment environment;

    @Before
    public void init(){
        EnvironmentTestUtils.addEnvironment(environment,"app.admin.user=zhangsan");
    }

    @Test
    public void testApplication(){
        Assert.assertEquals("1.0",environment.getProperty("app.version"));
        Assert.assertEquals("zhangsan",environment.getProperty("app.admin.user"));
    }
}



設定ファイルにプロパティを設定する以外に、テスト環境がいくつかの設定情報を読み込むことができる2つの方法があります。
1つ目は@SpringBootTestアノテーションでアノテーションパラメータープロパティを使用して値を指定する方法、2つ目はEnvironmentTestUtils.addEnvironmentメソッドを使用して設定する方法です。
テスト中です。

public interface UserDao {
    Integer createUser(String userName);
}


モックによるテスト方法

正式な環境は単なるインターフェイスであり、実装されておらず、管理のためのスプリングコンテナにも組み込まれていません。

@RunWith(SpringRunner.class)
public class UserDaoTest {

    // Use MockBean because there is no UserMapper object in the container at this time
    @MockBean
    public UserDao userDao;

    //Use BDDMockito to make predictions about the behavior of
    @Before
    public void init(){
        BDDMockito.given(userDao.createUser("admin")).willReturn(1);
        BDDMockito.given(userDao.createUser("")).willReturn(0);
        BDDMockito.given(userDao.createUser(null)).willThrow(NullPointerException.class);
    }

    @Test(expected=NullPointerException.class)
    public void testCreateUser() {
        Assert.assertEquals(Integer.valueOf(1),userDao.createUser("admin")) ;
        Assert.assertEquals(Integer.valueOf(0),userDao.createUser(""")) ;
        Assert.assertEquals(Integer.valueOf(1),userDao.createUser(null)) ;
    }
}



テスト

@RestController
public class UserController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @GetMapping("/user/home")
    public String home(){
        logger.info("user home");
        return "user home";
    }

    @GetMapping("/user/show")
    public String show(@RequestParam("id") String id){
        logger.info("book show");
        return "show"+id;
    }
}


コントローラに対するテスト

最初の方法 :
テストとして使用するControllerを定義します。

http://localhost:8080/user/home
http://localhost:8080/user/show?id=100


ブラウザでアクセスする

@RunWith(SpringRunner.class)
//specify web environment, random port
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {

    // This object is loaded into the spring container when running in the web environment
    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    public void testHome(){
        String context = testRestTemplate.getForObject("/user/home",String.class);
        Assert.assertEquals("user home",context);
    }

    @Test
    public void testShow(){
        String context = testRestTemplate.getForObject("/user/show?id=100",String.class);
        Assert.assertEquals("show10",context);
    }
}


テストクラスによるテスト

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = UserController.class)
public class UserControllerTest2 {

    @Autowired
    public MockMvc mockMvc;

    @Test
    public void testHome() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/user/home")).andExpect(MockMvcResultMatchers.status().isOk());
        mockMvc.perform(MockMvcRequestBuilders.get("/user/home")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect( MockMvcResultMatchers.content().string("user home"));
    }

    @Test
    public void testShow() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/user/show").param("id", "400")).andExpect( MockMvcResultMatchers.status().isOk());
        mockMvc.perform(MockMvcRequestBuilders.get("/user/show").param("id", "400")).andExpect( MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("show400"));
    }
}


2つ目の方法は、@WebMvcTestアノテーションを使用する方法です。

/**
 * @SpringBootTest cannot be used at the same time as @WebMvcTest
 * If you use the MockMvc object, you need to add the @AutoConfigureMockMvc annotation separately
 */
@RunWith(SpringRunner.class)
@SpringBootTest()
@AutoConfigureMockMvc
public class UserControllerTest3 {

    @Autowired
    private MockMvc mvc;

    @Test
    public void testHome() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/user/home")).andExpect(MockMvcResultMatchers.status().isOk());
        mvc.perform(MockMvcRequestBuilders.get("/user/home")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect( MockMvcResultMatchers.content().string("user home"));
    }

    @Test
    public void testShow() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/user/show").param("id", "400")).andExpect( MockMvcResultMatchers.status().isOk());
        mvc.perform(MockMvcRequestBuilders.get("/user/show").param("id", "400")).andExpect( MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("show400"));
    }
}


<イグ

WebMvcTest

WebMvcTest は、Web 環境で実行する必要はありませんが、どのコントローラをテストする必要があるかを示すコントローラを指定する必要があります。
この方法では、コントローラのみをテストし、コントローラ内の依存関係の一部を自分でモックする必要があります。
WebMvcTestは、スプリングコンテナ全体をロードしません。

第三の道
SpringBootTest()と@AutoConfigureMockMvcを組み合わせて使うことで、@SpringBootTestでテスト用のSpringコンテキスト環境をロードし、@AutoConfigureMockMvcでMockMvcクラスを自動構成しています。

/**
 * @SpringBootTest cannot be used at the same time as @WebMvcTest
 * If you use the MockMvc object, you need to add the @AutoConfigureMockMvc annotation separately
 */
@RunWith(SpringRunner.class)
@SpringBootTest()
@AutoConfigureMockMvc
public class UserControllerTest3 {

    @Autowired
    private MockMvc mvc;

    @Test
    public void testHome() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/user/home")).andExpect(MockMvcResultMatchers.status().isOk());
        mvc.perform(MockMvcRequestBuilders.get("/user/home")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect( MockMvcResultMatchers.content().string("user home"));
    }

    @Test
    public void testShow() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/user/show").param("id", "400")).andExpect( MockMvcResultMatchers.status().isOk());
        mvc.perform(MockMvcRequestBuilders.get("/user/show").param("id", "400")).andExpect( MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("show400"));
    }
}


アノテーションを使用すると、テストクラスが自動的に MockMvc クラスを構成することができます。