web-dev-qa-db-ja.com

Springサービスを正しくテストする

次のテストは、行usersRepo.save(user);NullPointerExceptionで失敗します。テストがperformProvision()関数に入るとき、usersRepoオブジェクトはnullであるためだと思います。

ただし、Webサービスが実際に実行されていて、コントローラーのエンドポイントにアクセスすると、すべてが正常に機能し、データベースが更新されます。

テストが失敗する理由はありますか?私の考えでは、PAutoProvisionは実際のデータベースを参照しますが、インメモリデータベースを処理する必要があるため、何らかの競合があるのではないでしょうか。また、アノテーションの設定が異なる例もたくさん見たので、それも問題になるのではないかと思います。

UsersRepoは、PAutoProvisionがSQLテーブルエンティティであるJpaRepositoryを拡張します。

これだけでは不十分な場合は、必要に応じてUsersRepoPAutoProvision、およびProvisionControllerクラスを提供できます。

サービス:

_@Service
public class ProvisionService {

    @Autowired
    private UsersRepo usersRepo;


    public String performProvision(UserData userData) {
        try {
            PAutoProvision user = new PAutoProvision(userData);
            usersRepo.save(user);  // OOTB CRUD repository functionality of springData to update/insert record data
            return String.format("Success: User %s has been added to the database", userData.getUserId());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.toString());
            System.out.println("\n\n Cannot perform the provisioning of the user " + userData.getUserId() + ": \n" + e.toString() + "\n\n");
        }

        return "problem";
    }
}
_

テスト:

_@RunWith(SpringRunner.class)
public class ProvisionServiceTest {

    private ProvisionService provisionService;

    @MockBean
    private UsersRepo usersRepo;

    @Before
    public void setUp(){
        provisionService = new ProvisionService();
    }

     @Test
    public void performProvision_shouldPass() {
        UserData userData = new UserData("userid", 30, 1, "spot", 1);
        try {
            String result = provisionService.performProvision(userData);
            assertThat(result, is(equalTo("Success: User userid has been added to the database")));
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.toString());
        }
    }
}
_

編集1:

_@Autowired_を追加し、setUp()メソッドを削除すると、次のようになります。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.autoprovision.ProvisionServiceTest': Unsatisfied dependency expressed through field 'provisionService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.autoprovision.ProvisionService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

5
Darrel Holt

JB Nizetがすでに述べたように、provisionServiceインスタンスはUserRepoを使用してsetUpメソッドで作成されるため、newモックはprovisionServiceインスタンスに注入されません。

テストは次のようになります。

@RunWith(SpringRunner.class)
public class ProvisionServiceTest {
    @Autowired // let Spring instantiate the instance to test
    private ProvisionService provisionService;

    @MockBean
    private UsersRepo usersRepo;

    @Test
    public void performProvision_shouldPass() {
        UserData userData = new UserData("userid", 30, 1, "spot", 1);

        String result = provisionService.performProvision(userData);
        assertThat(result, is(equalTo("Success: User userid has been added to the database")));
    }
}
4
iBiber

与えられた答えは役に立つようですが、誰かを助けることができる場合に備えて、Spring(IMHO)ではテストサービスはそれほど明白ではありません。 SpyBeanアノテーションは本当に便利であることがわかりました:

@RunWith(SpringRunner.class)
public class ProvisionServiceTest {
    @SpyBean
    private ProvisionService provisionService;
}

ソース: Spring Bootリファレンス-テスト

1
robin850