2017-08-26 20 views
0

Mockitoサービスを使用して、MyFinalClass2にスローされ、MyAbstractClassにキャッチされる例外をテストします。具体的なメソッドはMyFinalClass2のgetValueメソッドを呼び出します。このメソッドは、インターフェイス(MyInterfaceClass)オブジェクトを返します。以前の呼び出しに依存するMockito連鎖メソッド呼び出しが認識されない

私はMocking Chained calls in Concrete Class Mockitoで質問しました。ありがたいことに、提供されたソリューションは、MyFinalClassにあるgetObjectメソッドを呼び出すときに機能します。したがって、test1が動作します!

しかし今回は、@Autowiredではない別の最終クラス(MyFinalClass2)があり、MyFinalClassのメソッド呼び出しの後に呼び出されます。 MyFinalClass型のオブジェクトは、最初の呼び出しからMyFinalClassのメソッドに戻るものです。手動でTest2でMyException2をスローすると、認識されず、Test2でAssertionFailureが発生します。

また、次のコード行はまだ実装されていないため、NULLを返します。このメソッドが呼び出されたとき、私はTest2でMyFinalClass2の新しいインスタンスを返す理由は何ですか。

MyFinalClass2 myFinalClass2 = getObject(strName); 

以下のコードを参照してください。

public abstract class MyAbstractClass{ 

    @Autowired 
    private MyFinalClass myFinalClass; 

    //concrete method 
    protected MyInterfaceClass myConcreteMethod(String strName, String str) 
    { 
     try{ 
      //returns null as it has not yet been implemented 
      MyFinalClass2 myFinalClass2 = getObject(strName); 

      MyInterfaceClass b = getValue(myFinalClass2,str); 
      return b; 
     } catch(MyException e){ 
      LOGGER.log("ERROR THROWN" + e); 
     } catch(MyException2 e){ 
      LOGGER.log("ERROR THROWN" + e); 
     } 
    } 

    public MyFinalClass2 getObject(String strName){ 
     return myFinalClass.getObject(strName); 
    } 

    public MyInterfaceClass getValue(MyFinalClass2 myFinalClass2, String 
    str){ 
     return myFinalClass2.getValue(str); 
    } 

} 

public final class MyFinalClass { 

    public MyFinalClass2 getObject(String strName) throws MyException{ 
     **** HAS NOT YET BEEN IMPLEMENTED **** 
     return null; 
    } 

} 

public final class MyFinalClass2 { 
    public MyInterfaceClass getValue(String str) throws MyException2{ 
     **** HAS NOT YET BEEN IMPLEMENTED **** 
     return null; 
    } 
} 

public interface MyInterfaceClass { 
    **** HAS NOT YET BEEN IMPLEMENTED BY ANY CLASS **** 
    void getStuff(); 
} 

@ContextConfiguration(locations = "classpath:applicationContext-test.xml") 
@RunWith(PowerMockRunner.class) 
public class MyAbstractClassTest { 

    public static class ExampleConcreteClass extends MyAbstractClass{ 

    } 

    @InjectMocks 
    @Spy 
    ExampleConcreteClass exampleConcreteClass; 


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

    //THIS WORKS --- TEST 1 
    @Test 
    public void testIfExceptionOneIsThrown(){ 
     try{ 
      Mockito.when(exampleConcreteClass).getObject(name). 
      thenThrow(new MyException()); 

      exampleConcreteClass.myConcreteMethod(); 
      Assert.fail(); 
     }catch(MyException e){ 
      Assert.assertTrue(Boolean.TRUE); 
     } 
    } 

    //This test DOES NOT work --- TEST 2 
    @Test 
    public void testIfExceptionTwoIsThrown(){ 
     try{ 
      MyFinalClass2 myFinClass2 = new MyFinalClass2(); 
      String strName = "name"; 
      String str = "str"; 
      Mockito.when(exampleConcreteClass).getValue(myFinClass2,str). 
      thenThrow(new MyException2()); 

      Mockito.when(exampleConcreteClass).getObject(strName). 
      thenReturn(myFinClass2); 

      exampleConcreteClass.myConcreteMethod(); 
      Assert.fail(); 
     }catch(MyException e){ 
      Assert.fail(); 
     }catch(MyException2 e){ 
      Assert.assertTrue(Boolean.TRUE); 
     } 
    } 

} 

助けてください。大いに感謝!

答えて

3

まず、申し訳ありませんが、テストについて懸命に考える必要がある場合は、通常、コードが悪いという確かな兆候です。とにかく、Mockito 2は既にmock final classesにできるので、そこにPowerMockは必要ありません(しかし、あなたはそれを選ぶ必要があります)。

あなたexampleConcreteClass.myConcreteMethod()が、これMyException2は方法の範囲を離れることはないだろう... ...

} catch(MyException2 e){ 
     LOGGER.log("ERROR THROWN" + e); 
    } 

ので、MyException2を投げることができないため、また、あなたのテストは、まったく意味がありません。ログメッセージに変換されて破棄されます。それは方法を残さないので、それが動作しないと主張しようとします。あなたも、そこthrow e;のようなものを持っているでしょう。また

} catch(MyException2 e){ 
     LOGGER.log("ERROR THROWN" + e); 
     throw e; // re-throw e, otherwise it ends here 
    } 

を、単にヒントとして、あなたは簡単な書き込みによって、より簡単にそこに行うことができますがやろうとしているもの...

@Test(expected=MyException2.class) 
public void testIfExceptionTwoIsThrown() throws MyException, MyException2 { 

を。この方法では、MyException2がスローされないと、JUnitは自動的にテストに失敗するため、テストメソッドからすべてのtry-catchを削除できます。また、より多くの制御をしたい場合は、expectedパラメータよりももう少しパワフルで汎用性の高いJUnitのExpectedExceptionルールを参照することもできます(ただし、この場合は十分であるはずです)。

もちろん、あなたのメソッドがあなたのMyException2をキャッチしている限り、それはそのメソッドを離れることはないので、それをテストすることは役に立たないでしょう。

+1

この回答の一部は、私自身が書いたように読んでいます;-) – GhostCat

+0

@Florianありがとうございます。私はあなたの提案を受けた。私が主に直面していた問題は、Mockito.doReturnとMockito.when..thenReturnの違いを知らなかったためです。 – mashimarro

+0

Mockito.do ...(...)は、voidメソッドでも常に動作するので、これを行うための推奨された方法ですが、正直なところ、私はMockito.when(...)を使用する傾向があります(私は1つ、おそらく動作する必要があります)。 –

関連する問題