4

単純なプロジェクトで、@NotNull 検証 (およびその他のカスタム検証) をテストするのが好きです。

したがって、これを実行するいくつかの単体テストを作成しました。@Test(expect=ValidationException.class

ここで github にアップロードした問題を再現するための最小限の mavinized の例:

@Idが生成された値であればうまく機能することを認識しました。しかし@Id、システムによって が与えられた場合、検証は無視されます。

このクラスは、問題を再現するための最小限のセットアップを示します。

2 つのエンティティ (1 つは生成された値を持ち、もう 1 つは値を持たない:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class GeneratedId {
    @Id
    @GeneratedValue
    private Long    id;

    @NotNull
    private String  content;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class GivenId {
    @Id
    private Long    id;

    @NotNull
    private String  content;
}

単体テスト:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:/applicationContext.xml")
@Transactional
@ActiveProfiles("embedded")
public class MyEntityTest
{
    @Autowired GeneratedIdService   generatedIdService;

    @Autowired GivenIdService       givenIdService;

    // This test will pass
    @Test(expected = ValidationException.class)
    public void shouldNotAllowNullValues1()
    {
        this.generatedIdService.save(new GeneratedId());
    }

    // This test will fail
    @Test(expected = ValidationException.class)
    public void shouldNotAllowNullValues2()
    {
        this.givenIdService.save(new GivenId(1L, null));
    }
}

これはボイラープレートのサービスとリポジトリです

public interface GeneratedIdRepository extends JpaRepository<GeneratedId, Long> {
}

public interface GivenIdRepository extends JpaRepository<GivenId, Long> {
}

@Service
public class GeneratedIdService {
    @Autowired GeneratedIdRepository    repository;

    public GeneratedId save(final GeneratedId entity) {
        return this.repository.save(entity);
    }
}

@Service
public class GivenIdService {
    @Autowired GivenIdRepository    repository;

    public GivenId save(final GivenId entity) {
        return this.repository.save(entity);
    }
}

現在、Spring 3.1.4、Spring-Data 1.3.4、Hibernate 4.1.10、および Hibernate-Validator 4.2.0 を使用しています。

検証がスキップされた方法について何か提案はありますか?

編集1:

両方のエンティティでロンボクなしで試しましたが、それでもエラーが発生します。

4

2 に答える 2

5

EntityManager トランザクションがコミットまたはロールバックする前に持続性プロバイダーに強制的に をフラッシュさせたい場合は、手動でフラッシュするかsaveAndFlush(…)JpaRepository.

その理由は、自動生成された ID の場合、ID を Java オブジェクトにバインドできるように永続化プロバイダーがフラッシュする必要があるためです。手動で割り当てられた ID の場合、トランザクションの終了時よりも早い時点でフラッシュする必要がないため、永続化プロバイダーはデータベースのやり取りを回避します。

これらの技術的な詳細に加えて、永続化プロバイダーに依存してこの種の検証を行うことは、とにかくアーキテクチャ的に問題があると私は主張します。プロバイダーが違反を検出した場合、基本的に、あらゆる種類のビジネス ロジックを通じて無効なオブジェクトをパイプ処理したことになります。防御的にコード化する必要がないことを確認するには(どこでもnullチェック)、コンストラクターまたはセッターに渡された値をチェックすることにより、プロパティを強制的にnullにできないようにすることができます。このようにして、オブジェクトのインスタンスを取得するたびに、3 番目のフレームワークが呼び出された場合や、開発者が誤って呼び出すのを忘れた場合でも、値が になることはありません。null

于 2013-08-21T07:54:53.190 に答える