So I have a configuration properties bean
@Data
@ConfigurationProperties(prefix = "amount")
public class AmountProperties {
private BigInteger minimum;
private BigInteger maximum;
}
This configuration properties bean is used in a service
@Slf4j
@Data
@Service
@RequiredArgsConstructor
public class AmountService {
private final OtherService otherService;
private final AmountProperties amountProperties;
}
Now in testing I have a test class like this
@Slf4j
@ExtendWith(value = SpringExtension.class)
@EnableConfigurationProperties(value = AmountProperties.class)
@TestPropertySource("classpath:amount-test.properties")
public class CashOutServiceTest {
@Mock
private OtherService otherService;
@Autowired
private CashOutProperties cashOutProperties;
@InjectMocks
private AmountService amountService;
@Test
void a() {
assertNotNull(amountProperties);
log.debug("{}", amountProperties);
}
@Test
void b() {
assertNotNull(amountService.getAmountProperties());
log.debug("{}", amountService.getAmountProperties());
}
}
a test function succeed, but b test function fails. How do I inject amountProperties to amountService?
CodePudding user response:
You need to create a real AmountService class because you want to test it but you need to mock other classes used in AmountService class. Also, you can find mockito documentation says that doesn't mock everything.
@Slf4j
@ExtendWith(value = SpringExtension.class)
@EnableConfigurationProperties(value = AmountProperties.class)
@TestPropertySource("classpath:amount-test.properties")
public class CashOutServiceTest {
@Mock
private OtherService otherService;
@Autowired
private AmountProperties amountProperties;
private AmountService amountService;
@BeforeEach // If you using junit 4 use @Before annotation
public void init() {
MockitoAnnotations.openMocks(this);
amountService = new AmountService(otherService, amountProperties);
}
@Test
void a() {
assertNotNull(amountProperties);
log.debug("{}", amountProperties);
}
@Test
void b() {
assertNotNull(amountService.getAmountProperties());
log.debug("{}", amountService.getAmountProperties());
}
}
CodePudding user response:
You mix two approaches (SpringExtension
and InjectMocks
). If you used SpringExtension
- that means spring context will be created (use @MockBean
). If you used InjectMocks
- that means mocks will be created independently of spring(use @ExtendWith(MockitoExtensions.class)
), in this case EnableConfigurationProperties
and TestPropertySource
will not work for your tested service annotated by @InjectMocks
.
My understanding you want delegate creating of 'AmountProperties' by spring in this case please see my example:
@Slf4j
@ExtendWith(value = SpringExtension.class)
@EnableConfigurationProperties(value = AmountProperties.class)
@TestPropertySource("classpath:amount-test.properties")
@MockBean(OtherService.class)
public class CashOutServiceTest {
@Autowired
AmountProperties amountProperties;
@Autowired
AmountService amountService;
@Test
void a() {
assertNotNull(amountProperties);
log.debug("{}", amountProperties);
}
@Test
void b() {
assertNotNull(amountService.getAmountProperties());
log.debug("{}", amountService.getAmountProperties());
}
}
PS. @MockBean
can also be used at the field level if you want to use in a test.
public class CashOutServiceTest {
@MockBean
OtherService otherService;