[Flutter]Mockito MissingDummyValueError 에러 해결 기록

한상욱·2025년 2월 19일
0

에러해결모음

목록 보기
8/10
post-thumbnail

들어가며

최근 프로젝트에서 비슷한 유형의 클래스가 증가하여 상속을 적용하여 코드의 재사용성을 높이고자 하였습니다. 따라서, 기존의 클래스가 하나의 부모 클래스를 상속받도록 코드를 수정하고 있던 중 테스트 과정에서 마주했던 MissingDummyValueError 해결방법에 대해서 공유해보겠습니다.

사건의 발단

제가 진행하고있는 자취얌! 프로젝트에서는 재료 데이터가 이곳저곳에서 참조되는 구조입니다. 기존의 냉장고 재료는 냉장고 재료, 유저가 새로운 재료를 생성하기 위해서 사용하는 초기 재료, 그리고 레시피에서 사용되는 레시피 재료입니다.

각각의 클래스는 사용되는 목적은 다르지만, 공통의 프로퍼티를 갖습니다. 이름, 카테고리 등등이 있습니다. 상속을 사용하게 되면 각 유형이 공통의 프로퍼티가 변경되면 유지보수가 힘들게 됩니다. 하지만, 현재의 재료 데이터는 이름 속성을 반드시 공유하므로 크게 문제가 될 것이 없었기에 class modifier와 상속을 통해 재사용성과 안정성을 높이고자 하였습니다.

/// 모든 Ingredient 유형은 부모로 [Ingredient]를 상속받습니다.
///
/// 최 상단의 부모 클래스로서, 코드의 재사용을 위해서 사용됩니다.
base class Ingredient {
  final String name;

  Ingredient({required this.name});
}

base class인 Ingredient는 여러 유형의 하위 재료 유형으로 상속됩니다. 이름이라는 공통의 성질을 공유하게 됩니다. 그렇기에 이런식으로 코드를 상속받습니다.

final class RefreginatorIngredient extends Ingredient with EquatableMixin {
 ....
 
final class InitialIngredient extends Ingredient with EquatableMixin {

각각 냉장고 재료와 초기 재료 데이터를 의미합니다. EqautableMixin은 추후에 사용될 가능성이 있기에 추가하였습니다.

각각의 class는 final로 정의되어 더이상의 상속은 불가능합니다. 이로써, 예상치못한 실수를 줄이고자하였습니다.

그러나, 이렇게 변경된 이후로 테스트 과정에서 문제가 생겼습니다.

문제의 코드

이 테스트 코드는 서버 API 관련 단위 테스트입니다.

    test("updateIngredient메소드를 통해서 기존의 재료정보를 수정할 수 있다.", () async {
      when(ingredientRepository.updateIngredient(any)).thenAnswer(
        (_) async => RefreginatorIngredient(
          id: 1,
          name: "updated",
          category: IngredientCategory.egg,
          isFreezed: true,
          startAt: DateTime(2024, 12, 2),
          endAt: DateTime(2024, 12, 30),
        ),
      );

      final prevIngredient = ingredientViewModel.myFreezedIngredients.first;

      ingredientViewModel.selectPrevIngredient(prevIngredient);
      ingredientViewModel.updateIngredientName("updated");
      await ingredientViewModel.updateIngredient();
      final currIngredient = ingredientViewModel.myFreezedIngredients.first;
      expect(ingredientViewModel.myFreezedIngredients.length, 3);
      expect(currIngredient.name, "updated");
    });

이는 재료 갱신 단위 테스트 코드로 when을 통해 테스트 스텁에 가상의 updateIngredient 메서드를 지정하고 수행됩니다. 하지만 여기서 아래와 같은 에러 메시지가 발생합니다.

 This means Mockito was not smart enough to generate a dummy value of type
  'RefreginatorIngredient'. Please consider using either 'provideDummy' or 'provideDummyBuilder'
  functions to give Mockito a proper dummy value.
  
  Please note that due to implementation details Mockito sometimes needs users
  to provide dummy values for some types, even if they plan to explicitly stub
  all the called methods.

RefreginatorIngredient를 더미로 생성하지 못한다는 이야기입니다.

해결방법

이 이슈는 Mockito 깃허브 레포에 이미 언급이 되어 있었습니다.

아마도 이 분께서는 sealed class를 통해서 수행하다가 해당 에러를 마주하신듯 합니다. 해결법이 함께 공유되어있었습니다.

providerDummy를 통해 더미 데이터를 임의로 추가해주면 해결된다고 합니다. 저도 이를 통해서 해결할 수 있었습니다.

    test("updateIngredient메소드를 통해서 기존의 재료정보를 수정할 수 있다.", () async {
      provideDummy(
        RefreginatorIngredient(
          id: 1,
          name: "updated",
          category: IngredientCategory.egg,
          isFreezed: true,
          startAt: DateTime(2024, 12, 2),
          endAt: DateTime(2024, 12, 30),
        ),
      );
      when(ingredientRepository.updateIngredient(any)).thenAnswer(
        (_) async => RefreginatorIngredient(
          id: 1,
          name: "updated",
          category: IngredientCategory.egg,
          isFreezed: true,
          startAt: DateTime(2024, 12, 2),
          endAt: DateTime(2024, 12, 30),
        ),
      );

+

추가적으로 이 이슈에 대해서 아직은 당장 우선순위가 낮기에 추후 개선할 예정이라고 합니다...

profile
자기주도적, 지속 성장하는 모바일앱 개발자의 기록

0개의 댓글