2013-06-23 12 views
14

私は自分のクラスをテストするためにどれだけ深く(ユニット)入るべきか自分に尋ねています。 例として、次の単純なクラスがあります。ユニットテストの注釈?

import javax.annotation.security.PermitAll; 
import javax.ejb.Singleton; 
import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 


@Path(value = "ping") 
@Singleton 
@PermitAll 
public class PingRestService { 

    @GET 
    @Produces(MediaType.TEXT_PLAIN) 
    public String pingMethod(){ 
     return "pong"; 
    } 

} 

私はユニットテスト以下の書いた:

import static org.junit.Assert.*; 
import java.lang.reflect.Method; 
import javax.annotation.security.PermitAll; 
import javax.ejb.Singleton; 
import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 

import org.junit.Test; 


public class PingRestServiceTest { 

    PingRestService prs = new PingRestService(); 

    @Test 
    public void testClassAnnotations(){ 
     assertEquals(3, prs.getClass().getAnnotations().length); 

     assertTrue(prs.getClass().isAnnotationPresent(PermitAll.class)); 
     assertTrue(prs.getClass().isAnnotationPresent(Singleton.class)); 
     assertTrue(prs.getClass().isAnnotationPresent(Path.class)); 

     assertEquals("ping", prs.getClass().getAnnotation(Path.class).value()); 

    } 

    @Test 
    public void testPingMethodAnnotations() throws SecurityException, NoSuchMethodException{ 

     Method method = prs.getClass().getDeclaredMethod("pingMethod"); 
     assertEquals(2, method.getAnnotations().length); 

     assertTrue(method.isAnnotationPresent(GET.class)); 
     assertTrue(method.isAnnotationPresent(Produces.class)); 

     assertEquals(1, method.getAnnotation(Produces.class).value().length); 
     assertEquals(MediaType.TEXT_PLAIN, method.getAnnotation(Produces.class).value()[0]); 
    } 

    @Test 
    public void testPingMethod() { 
     assertEquals("pong", prs.pingMethod()); 
    } 

} 

それは理にかなっていますか? また、すべての注釈テスト(testClassAnnotations、testPingMethodAnnotations)をスキップして、返す文字列( "pong"、testPingMethod)のみをテストする必要がありますか?

一部の注釈はビジネスロジックの一部(例:PermitAll)なので、テストする必要があります。

+1

webserviceを作成してテストするフルクラスで統合テストを行います安らかなAPI;これは単体テストとは別にすべきです。 –

+1

追加のメディアタイプを@Producesアノテーションに追加すると、テストが中断しますが、テスト中のメソッド内のロジックは変更されません。無意味なテストと同様に脆弱と思われる。 – JamesB

+0

しかし、テストが壊れると、それは悪いですか?私は、このメソッドが特定のメディアタイプだけを生成することを期待しています。別のメディアタイプを追加すると、テストを調整する必要があります。それは良い習慣ではありませんか? PermitAllのようなものをテストすることは、統合テストでもっと複雑になる可能性があります。 Javaクラスの標準isAnnotationPresentメソッドを使用すると、1行のコードでそれをカバーできます。 – lappo

答えて

5

ほとんどの場合、コードの機能をテストし、実装方法はテストしません。これはBlack Box Testingと呼ばれます(http://en.wikipedia.org/wiki/Black-box_testing参照)。 テストを実装するときは、「テストするユニットの入力値はどうなりますか?また、期待される結果は何ですか? テストでは、入力値でコードを呼び出し、期待どおりの結果が得られるようにコードをチェックします。 時間の経過とともに、機能を変更することなくコードを最適化できます。テストを変更する必要はありません。しかし、それを再実行して、それがまだ同じように動作することを確認することができます。たとえそれが異なって実装されています。あるいは、テストした機能に副作用をもたらす実装の詳細を変更することもできます。この場合も、テストを変更する必要はありませんが、再実行するだけです。 単純なケースでは、入力と1つの静的出力がないので、単にメソッドを呼び出して "pong"が返されるかどうかを確認できます。しかし、実際にテストされた事例はそれほど単純ではありません。

編集:@PermitAllが設定するセキュリティと「@Path」が入力として設定するURLパスを確認し、「Boris the Spider」と「Avi」の方法で統合テストを行います。しかし、他の注釈は実装固有のものです。

3

私の意見では、それらの注釈はクラスの側面であり、実際の目的ではないので、単体テストにするべきではありません。 明日はJAX-RSの代わりにSpring MVCを使用しますが、クラスが同じ動作をしてユニットテストが同じになるようにします