[JAVA] Conseils pour tester avec mock pour les classes utilisant @value

C'est le 9e jour du Calendrier de l'Avent de l'Université des sciences de Tokyo 2019.

Cette fois, j'écrirai sur la méthode / les astuces pour tester une classe qui utilise l'annotation @ Value dans le framework Java Spring.

Qu'est-ce que «@ Value»?

L'annotation «@ Value» est une annotation utilisée lorsque vous souhaitez injecter une valeur à partir d'un autre fichier. Pour Spring Boot Si les paramètres par défaut sont utilisés, les valeurs décrites dans application.yml ou application.properties seront lues et injectées.

Plus précisément, c'est dans ce format. Tout d'abord, écrivez la valeur dans application.yml.

application.yml


sample.threshold : 1

Et dans l'argument de l'annotation

@Value("${Clé}")

Ensuite, ajoutez l'annotation «@ Value» aux champs et arguments de la classe.

En particulier

HogeCoordinator.java


@Service
public class HogeCoordinator {

  @value("${sample.threshold}")
  private Integer threshold;

  @Autowired
  private HogeService hogeService;

  public void hoge() {
    hogeService.fuga(threshold);
  }
}

C'est une telle image. Si vous écrivez @ value (" $ {sample.threshold} ") dans le champ threshold de la classe HogeCoordinator, 1 sera lu à partir de la clé décrite dans application.yml, et lorsque l'application sera exécutée, elle sera injectée.

Cela présente l'avantage de pouvoir collecter et gérer les valeurs spécifiques à l'application dans un seul fichier.

Test des classes en utilisant @ Value

Ensuite, c'est une méthode de test pour la classe en utilisant «@ Value» du sujet principal.

La cible du test est HogeCoordinator.java. Lorsque vous utilisez «@ Value», si vous écrivez le test général suivant, la valeur ne sera pas injectée dans la cible à laquelle «@ Value» est donnée.

FailedHogeCoordinatorTest.java


public class FailedHogeCoordinatorTest {

  @InjectMocks
  private HogeCoordinator hogeCoordinator;

  @Mock
  private HogeService hogeService;

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

  //Omis ci-dessous
}

Par conséquent, utilisez la méthode setField de la classe ReflectionTestUnits. Dans l'argument de la méthode, spécifiez l'instance cible, le nom du champ à injecter et la valeur à injecter.

Pour utiliser cette méthode, il est nécessaire de créer une instance de HogeCoordinator, alors gardez-la nouvelle.

Si vous écrivez un test basé sur cela, il ressemblera à ceci.

SuccessHogeCoordinatorTest.java


public class SuccessHogeCoordinatorTest {

  @InjectMocks
  private HogeCoordinator hogeCoordinator = new HogeCoordinator();

  @Mock
  private HogeService hogeService;

  @Before
  public void setup() {
    ReflectionTestUnits.setField(hogeCoordinator, "threshold", 1);
    MockitoAnnotations.initMocks(this);
  }

  //Omis ci-dessous
}

En faisant cela, la valeur sera injectée dans le champ avec «@ Value».

L'astuce est que vous devez créer une instance de la classe qui injecte la maquette au moment du test, il est donc préférable de ne pas faire d'injection de constructeur lors de la DI.

La classe HogeCoordinator qui fait l'objet de ce test est DI utilisant @ Autowired, mais si vous effectuez une injection de constructeur en utilisant @ RequiredArgsConstructor de Lombok comme indiqué ci-dessous, le nombre d'arguments de constructeur augmentera. Cela rend la création d'une instance fastidieuse.

HogeCoordinator.java


@Service
@RequiredArgsConstructor
public class HogeCoordinator {

  @value("${sample.threshold}")
  private Integer threshold;

  private final HogeService hogeService;

  public void hoge() {
    hogeService.fuga(threshold);
  }
}

Par conséquent, lors de l'injection dans une classe à tester à l'aide de la méthode setField de la classe ReflectionTestUnits, il est plus facile d'éviter l'injection de constructeur.

Résumé

Lors du test par rapport à une classe avec «@ Value», utilisez la méthode setField de la classe ReflectionTestUnits pour injecter la valeur. À ce moment-là, si le DI de la classe à tester est défini sur une méthode autre que l'injection de constructeur, il sera plus facile de générer une instance pendant le test et ce sera plus facile à tester.

à la fin

J'ai une connexion avec OB cette fois, alors j'ai décidé de participer au calendrier de l'Avent. Je suis reconnaissant à @piffett de m'avoir fourni un endroit précieux pour participer au calendrier de l'Avent pour la première fois. Merci beaucoup.

Les références

Document officiel de printemps (@Value)

Spring Official Documents (General Testing Utilities)

Recommended Posts

Conseils pour tester avec mock pour les classes utilisant @value
Remarques sur l'utilisation de BLE dans les applications iOS
Procédure de construction d'environnement pour l'utilisation de PowerMock avec JUnit
Tester le code à l'aide d'une maquette avec JUnit (centre EasyMock)
astuces pour java.nio.file.Path
Test avec com.google.testing.compile