[英]Injecting a mock in Spring application context creates a copy
我有一個看起來像這樣的測試類:
@SpringApplicationConfiguration(classes = RecipesApplicationTest.class) // This test class will configure its own context
@ComponentScan("com.mysmartfridge.domain.recipes") // Scan recipes domain package so that domain services are available
@Import(RecipesApplication.class) // Load the bean that we want to test.
public class RecipesApplicationTest {
@ClassRule
public static final SpringClassRule SCR = new SpringClassRule();
@Rule
public final SpringMethodRule SMR = new SpringMethodRule();
@Autowired
private RecipesRepository recipesRepository;
private final RecipesRepository recipesRepositoryMock = Mockito.mock(RecipesRepository.class); // final mocks because they are given to spring context.
// Get the service to test from the context
@Autowired
RecipesApplication recipesApplication;
@Test
public void addingARecipeShouldMakeItAvailableInRandomRecipes() {
//given
RecipeDto dto = new RecipeDto();
dto.title="test";
dto.ingredients = new ArrayList<>();
dto.steps = new ArrayList<>();
final List<Recipe> recipesInMock = new ArrayList<>();
Mockito.when(recipesRepository.save(Mockito.any(Recipe.class))).thenAnswer(new Answer<Recipe>() {
@Override
public Recipe answer(InvocationOnMock aInvocation) throws Throwable {
Recipe arg = aInvocation.getArgumentAt(0, Recipe.class);
recipesInMock.add(arg);
return arg;
}
});
Mockito.when(recipesRepository.findAll()).thenAnswer(new Answer<List<Recipe>>() {
@Override
public List<Recipe> answer(InvocationOnMock aInvocation) throws Throwable {
return recipesInMock;
}
});
//when
dto = recipesApplication.createRecipe(dto);
RecipeDto randomDto = recipesApplication.findRandomRecipe();
//then
Assertions.assertThat(randomDto).isEqualTo(dto);
}
// Inject the recipeRepository mock in the context
@Bean
RecipesRepository recipesRepository() {
return recipesRepositoryMock;
}
}
我的問題是兩個字段recipesRepositoryMock和recipesRepository不是同一對象。 因此,如果我在設置答案時嘗試用recipesRepositoryMock替換recipesRepository(例如,如果我在when(recipesRepositoryMock.save()).thenAnswer(...)
),那么它將無法正常工作,則永遠不會調用自定義答案。
我希望能夠擺脫@Autowired recipesRepository的要求,該方法與recipesRepositoryMock有點重復...
是因為春天我的bean周圍添加了代理嗎?
您最好刪除private final RecipesRepository recipesRepositoryMock = Mockito.mock(RecipesRepository.class);
如果要模擬Spring bean,則必須使用@Autowired
為Spring創建它。
因此,您的測試可能類似於:
@SpringApplicationConfiguration(classes = RecipesApplicationTest.class) // This test class will configure its own context
@ComponentScan("com.mysmartfridge.domain.recipes") // Scan recipes domain package so that domain services are available
@Import(RecipesApplication.class) // Load the bean that we want to test.
public class RecipesApplicationTest {
@ClassRule
public static final SpringClassRule SCR = new SpringClassRule();
@Rule
public final SpringMethodRule SMR = new SpringMethodRule();
@Autowired
private RecipesRepository recipesRepository;
// Get the service to test from the context
@Autowired
RecipesApplication recipesApplication;
@Test
public void addingARecipeShouldMakeItAvailableInRandomRecipes() {
// your test
}
// Inject the recipeRepository mock in the context
@Bean
RecipesRepository recipesRepository() {
return Mockito.mock(RecipesRepository.class);
}
}
聽起來您正在嘗試依賴自動RecipesRepository
以便Spring正確地將RecipesRepository
實例作為依賴項注入RecipesApplication
。 這個問題似乎與您的相似。 話雖這么說,我很想聲明一個重復項,因為您可能沒有使用[ReflectionTestUtils][2]
類的東西。 相反,嘗試僅刪除recipesRepository
中的recipesRepository
字段, RecipesApplicationTest
保留recipesRepositoryMock
字段。 但是,在dto = recipesApplication.createRecipe(dto)
行之前,請嘗試查看是否可以通過諸如recipesApplication.setRecipesRepository(recipesRepositoryMock)
類的調用手動將recipesRepositoryMock
注入recipesApplication
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.