Spring / SpringBoot新手。我有一个代表玩具车经销商的界面:
public interface DealershipService {
Long getRevenue();
void sell(Car car);
void buy(Car car);
List<Car> findByMake(String make);
List<Car> findByMakeAndModel(String make, String model);
List<Car> findByMakeModelAndYear(String make, String model, String year);
List<Car> findByYearRange(String yearLowInclusive, String yearHighInclusive);
List<Car> findInCostRange(long costLowInclusive, long costHighInclusive);
}
及其实现,其中只有buy()
和sell()
方法是真正相关的方法:
@Slf4j
@Data
@Service
public class DealershipServiceImpl implements DealershipService {
@Value("${revenue}")
private Long revenue;
private final CarRepository carRepository;
@Autowired
public DealershipServiceImpl(CarRepository carRepository) {
this.carRepository = carRepository;
}
@Override
public void sell(Car car) {
carRepository.removeFromRepository(car.getVin());
revenue += car.getCostInUSD();
log.info("Sold car {}. Current revenue: {}", car, revenue);
}
@Override
public void buy(Car car) {
if (revenue >= car.getCostInUSD()) {
carRepository.addToRepository(car);
revenue -= car.getCostInUSD();
log.info("Bought car {}. Current revenue: {}", car, revenue);
} else {
log.warn("Unable to buy car {}; we're broke!", car);
throw new InsufficientRevenueException();
}
}
.
.
.
买车会减少可用收入,而卖车会增加可用收入。在我的application.properties
文件中(在main
和test
下),revenue
的价值是1_000_000L
(据推测是100万美元)。
为了测试这个实现,我编写了以下代码:
@SpringBootTest(classes = TestConfig.class)
public class DealershipServiceIT {
@Autowired
private DealershipService dealershipService;
@Test
public void whenNoTransactions_TotalRevenueIsAMil(){
assertThat(dealershipService.getRevenue(), is(1_000_000L));
}
@Test
public void whenMakingTransactions_revenueIsAffected(){
Car car = Car.builder().year(2006).vin("1234").costInUSD(10_000L).make("Nissan").model("Sentra").build();
dealershipService.buy(car);
assertThat(dealershipService.getRevenue(), is(990_000L));
}
}
问题是whenMakingTransactions_revenueIsAffected()
的动作影响了注入到类中的单例字段dealershipService
,因此,当我运行类的所有测试时,这个测试首先运行(我不知道为什么测试没有按照编写的顺序运行),这个测试成功而whenNoTransactions_TotalRevenueIsAMil()
失败,这是因为收入福尔斯了10 k,然后第一个测试看到了dealershipService
的同一个单例示例。
如果我通过在DealershipServiceImpl
上添加@Scope("prototype")
来使DealershipServiceImpl
成为原型bean,这个问题就得到了解决,但是我不太确定这是否是一个好的Spring设计;Bean默认为单例是有原因的。
因此,我希望找到一种方法,将测试中注入的DealershipService
视为原型 *,以便进行测试 *,如果可能的话。实际上,无论何时进入新测试,我都需要将新的DealershipService
注入测试。使原始DealershipService
成为原型是唯一的可能性吗?
1条答案
按热度按时间xoefb8l81#
您的测试重用了应用程序上下文,为了使它们彼此独立,您应该使用
@DirtiesContext
注解:@DirtiesContext
指示底层Springx 1 m2n1x在测试执行期间已被污染(也就是说,测试以某种方式修改或损坏了它-例如,通过更改单例bean的状态),并且应该关闭。当应用程序上下文被标记为脏时,它将从测试框架的缓存中删除并关闭。因此,底层Spring容器将被重新构建以用于任何需要具有相同配置元数据的上下文的后续测试。例如,您可以如下所示注解测试类: