2017-02-15 4 views
0

私はSpring MVCを使用するプロジェクトを持っています。 私はプロジェクトのアーキテクチャにあるサービスモジュールの単位テスト、 を書こうとしています。 すべてのサービスクラスは、 "BaseService"という名前のスーパークラスから拡張されています。 BaseServiceはこのようなものです。このような依存関係を注入したスーパークラスを模擬する方法

"voToBvo (S vo, Class<?  extends BaseBVO> bvoClass") 

public abstract class BaseService { 

private static final Logger logger = LoggerFactory.getLogger(BaseService.class); 

@Autowired(required = true) 
private HttpServletRequest request; 

@Autowired 
private ReloadableResourceBundleMessageSource messageSource; 

/* 
* Injecting Mapper 
*/ 
@Resource 
private Mapper mapper; 
... 

public <T extends BaseBVO, S extends BaseVO> T voToBvo (S vo, Class<?  extends BaseBVO> bvoClass) { 

    if (vo != null) 
    { 
     return (T) mapper.map(vo , bvoClass); 
    } 
    else 
    { 
     return null; 
    } 
} 

今、私はこの方法を使用するサービス・モジュール内のメソッドを持っている

public List<AdcOptionBVO> findOptionByAyantDroitIdAndProduitId (Long idAyantDroit, String idProduit) { 

    .... 

     list = listVoToBvo(adcList , AdcOptionBVO.class); 
     logger.info("Returning List of ayrp count= {}" , list.size()); 

    return list; 
} 

私のテストは、このようなものです:

@RunWith(MockitoJUnitRunner.class) 
public class AdcServiceImplTest{ 

@Mock 
private Mapper mapper; 

    @Test 
public void shouldSuccessFindOptionByAyantDroitIdandProduitId() { 
    //Given 
    List<AdcVO> adcVOList = new ArrayList<>(); 
    adcVOList.add(new AdcVO()); 

    List<AdcOptionBVO> listAdcOptionBVO = new ArrayList<>(); 
    listAdcOptionBVO.add(new AdcOptionBVO()); 

    List<BaseBVO> baseBVOs = new ArrayList<>(); 

    //When 
    when(repository 
      .finAdcByOptionOrderByRUAndPrio(anyLong(), anyString())).thenReturn(adcVOList); 

    when(baseService.listVoToBvo(adcVOList, AdcOptionBVO.class)).thenReturn(baseBVOs); 


    //Then 
    assertEquals(adcService 
      .findOptionByAyantDroitIdAndProduitId(anyLong(), anyString()).size(), adcVOList.size()); 

} 
} 

マッパーを呼び出すときにBaseService.javaでjava.lang.NullPointerExceptionが発生する。

@Resource 
private Mapper mapper; 

マッパーはnullです!

私はメソッドをモックとしたい:

listVoToBvo(adcList , AdcOptionBVO.class); 

助けてください。

答えて

1

ソリューションは、私はインスタンス化するので、私はマッパーマッパーを模擬テストでサービス のコンストラクタでサービスコールsuper(mapper);で、その後、私の場合(マッパー)で、注入されたパラメータでabstarctクラスのコンストラクタを追加することです私のクラスは@Beforeであるので、mapperはabstarctクラスにMockとして渡され、ヌルではありません。私はそのクレアを願って

1

あなたのテストが現在セットアップされているので、基本クラスの注入されたアイテムは注入されません。

  1. ラン(SpringJUnit4ClassRunner.classという名前の)春のテストランナーを使用して: あなたがこの問題を解決するために使用できる2つの手法があります。これは、範囲外の統合テストでは問題ありません。
  2. 注射を手作業で行う。リフレクションを使用して、BaseServiceクラスのマッパーをモックオブジェクトに設定します。 2.

使用法では、リフレクションを使用してデータメンバを設定し、テストに使用ユーティリティを作成します。 "set parent class variable reflection java"またはそれに近いものをgoogle検索で実行すると、反射コード例が見つかるでしょう。 ユーティリティは、リフレクションコードをラップし、データメンバー名、クラスオブジェクト、値を設定するオブジェクトへの参照、およびリフレクションを実行するために必要なその他のもの。

もう1つの方法は、リフレクションユーティリティ(Google、Apache、およびSpring)がすべて必要であることを見つけることです。ここで

は(非機能)の例である:

public static void setFieldObject(
    final String fieldName, 
    final Object fieldValue, 
    final Object targetObject, 
    final Class targetClass) 
throws 
    NoSuchFieldException, 
    IllegalAccessException 
{ 
    final Field targetField; 

    targetField = targetClass.getDeclaredField(fieldName); 
    targetField.setAccessible(true); 

    targetField.set(
     targetObject, 
     fieldValue); 
} 
0

実際にあなたのコードは何とかそれほど明確ではない、しかしautowiredフィールドを模擬するためにMockitoを使用すると、あなたはちょうど手順を実行する必要があり、非常に複雑ではありません。

は、我々はBaseServiceのためのユニットテストを作成したいとしましょう:

public class BaseServiceTest { 

    private static final BaseVO TEST_BaseVO = //intialize here...; 
    private static final BaseBVO TEST_BaseBVO = //intialize here...; 

    private static final BaseBVO TEST_BaseBVO_RESULT = //intialize here...; 

    @InjectMocks 
    private BaseService baseService; 

    @Mock 
    private HttpServletRequest request; 

    @Mock 
    private ReloadableResourceBundleMessageSource messageSource; 

    @Mock 
    private Mapper mapper; 

    @BeforeMethod 
    public void initMocks(){ 
     //This line of code is so important!! to initialize annotated fields. without it these fields would be null. 
     //Or just annotate this class with @RunWith(MockitoJUnitRunner.class) 

     MockitoAnnotations.initMocks(this); 

     //Here all fields annotated with @Mock or @Spy should be initialize and injected into BaseService. 
    } 

    @Test 
    public void voToBvo_should_return_null_when_vo_is_null(){ 

     //Call testing method 
     BaseBVO result = baseService.voToBvo(null, TEST_BaseBVO.class); 

     //Assertions 
     Assert.assertNull(result); 
    } 

    @Test 
    public void voToBvo_should_not_return_null_when_vo_is_not_null(){ 

     //Mock calls 
     Mockito.doReturn(TEST_BaseBVO_RESULT).when(mapper).map(TEST_BaseVO, TEST_BaseBVO.class) 

     //Call testing method 
     BaseBVO result = baseService.voToBvo(TEST_BaseVO, TEST_BaseBVO.class); 

     //Assertions 
     Assert.assertNotNull(result); 
     Assert.assertEquals(TEST_BaseBVO_RESULT, result); 
    } 
} 

それがこのユニットテストが愚かであることをあなたに聞こえるかもしれない(実際にはそれが愚かである:P)が、それが基本的な手順を説明しMockitoを使用してUTを成功させ、NPEを防ぐ方法も作成します。

3

私はあなたに最初にあなたのBaseServiceファイルを変更することをお勧めします。

private HttpServletRequest request; 
@Autowired(required = true) 
public void setSpellChecker(HttpServletRequest request){ 
    this.request = request; 
} 

@Autowired 
private ReloadableResourceBundleMessageSource messageSource; 
public void setSpellChecker(ReloadableResourceBundleMessageSource messageSource){ 
    this.messageSource = messageSource; 
} 

を次のように@Autowiredを書く方法を変更 そして、あなたはそれを行うだろうと、今、あなたは簡単に依存してテストケースを達成することができます。

関連する問題