2017-11-16 11 views
0

私のWebサービスのメソッドをユニットテストするのに苦労しています。これらのメソッドはすべて、注入されたWebServiceContextを参照し、そこからuserIdを取得して、そのユーザーが承認されていることを確認します。私はWebServiceContextをモックアップする方法を理解しようと多くの時間を費やしましたが、何を試みてもコンテキストは常にnullです。Webサービスに注入されたWebServiceContextを模擬する方法

私の最終目標は、テストクラスで指定したuserIdを返すことで、残りのメソッドの実際の機能をテストできるようにすることです。

これは、メソッドのほとんどが設定されているかのストリップダウンバージョンです:

@HandlerChain(file = "/handler.xml") 
@javax.jws.WebService (...) 
public class SoapImpl 
{ 
    @Resource 
    private WebServiceContext context; 

    public void methodUnderTest() 
    { 

     // context is NULL here - throws null pointer 
     Principal userprincipal = context.getUserPrincipal(); 

     String userId = userprincipal.getName(); 


     // Do some stuff - I want to test this stuff, but can't get here 
    } 

} 

は、これは私が文脈とテスト

@RunWith(MockitoJUnitRunner.class) 
@PrepareForTest(SoapImpl.class) 
public class SoapImplTest { 

    @Mock 
    WebServiceContext context; 

    @Mock 
    Principal userPrincipal; 

    @Before 
    public void setup() { 
     MockitoAnnotations.initMocks(this); 
    } 

    @Test 
    public void testCreateOverrideRules() { 

     SoapImpl testImpl = new SoapImpl(); 

     when(context.getUserPrincipal).thenReturn(userPrincipal); 
     when(userPrincipal.getName()).thenReturn("testUser"); 

     testImpl.methodUnderTest(); 

     assertEquals(1,1); 
    } 

} 

を模擬しようとしていますどのように私は依存性注入について知っていますコンテクストが@resourceアノテーションを介して注入されるため、ここでコンストラクタを介してコンテキストを渡すことはできますが、ここでそれを行うことはできません。コンストラクタは決して呼び出されません。私はそれをどのように実装するのか完全に理解していません。

また、WebServiceContextとPrincipalはインタフェースであるため、インスタンス化することはできません。このため、これはさらに混乱します。誰でもここで私を助けることができますか? WebServiceContextとPrincipalをどうやって模擬することができるので、このメソッドのこの部分を過ぎて実際にテストしたいものに移動できますか?

UPDATE 私は以下のコードに見られるよう@InjectMocks注釈を使用して問題を解決することができました:

@RunWith(MockitoJUnitRunner.class) 
@PrepareForTest(SoapImpl.class) 
public class SoapImplTest { 

    @InjectMocks 
    private SoapImpl testImpl = new SoapImpl(); 

    @Mock 
    WebServiceContext context; 

    @Mock 
    Principal userPrincipal; 

    @Before 
    public void setup() { 
     MockitoAnnotations.initMocks(this); 
    } 

    @Test 
    public void testCreateOverrideRules() { 

     when(context.getUserPrincipal).thenReturn(userPrincipal); 
     when(userPrincipal.getName()).thenReturn("testUser"); 

     testImpl.methodUnderTest(); 

     assertEquals(1,1); 
    } 

} 

答えて

0

私は@InjectMocksアノテーションを使用して私の問題を解決することができました。これにより私は模擬したオブジェクトをクラスに注入することができました。以下の2つのリソースはこれを考え出すのに役立ちました:私はいくつかの新しいコードで私の質問を更新しました

https://docs.oracle.com/javaee/6/tutorial/doc/bncjk.html

Injecting @Autowired private field during testing

0

1)あなたは、あなたの中にコンテキストを設定し、コンストラクタやセッターを持っている必要がありますテスト中のクラス。そうでない場合は、この正確な理由で1つを追加することをお勧めします。

2)WebServiceContextまたはPrincipalをインスタンス化する必要はありません。 Mockito.mock(WebServiceContext.class)とMockito.mock(Principal.class)を使用して、単純にモックを作成します。次に、Mockito.when(mockWebServiceContext)を追加して動作を追加します。

ユニットテストを行っている場合は、テストするメソッドのロジックのみをテストし、追加のメソッドや統合はテストしないことに注意してください。これが、WebServiceContextとPrincipalの両方の模擬インスタンスを必要とする理由です。あなたは統合テスト(おそらく)を望んでいません。

+0

。私はセッターを追加しました。しかし、私はまだセッターがプライベートなので、コンテキストをモックできません。セキュリティ上の理由からこれを公開する方法は望ましくありません。あなたはこれを回避する方法を知っていますか? – mwelk11

+0

理想的には、コンストラクターベースの注入を使用し、WebServiceContextをとるパブリックコンストラクター(セッターの代わりに)を使用することをお勧めします。このようにして、あなたのSoapImplクラスは不変(ステートレスシステムの望ましい特性)になります。しかし、セッタールートを選択する場合は、セッターをパブリックにする必要があります。 –

+0

これで、Mockオブジェクトでコンストラクタを呼び出すことができます。 –

関連する問題