我有以下Spring
组件,我试图进行单元测试:
@Component
public class OrderService {
private final DatabaseConnection dbConnection;
private final String collectionName;
@Autowired
public OrderService(
DatabaseConnection dbConnection,
DatabaseConfig databaseConfig) {
this.dbConnection = dbConnection;
this.collectionName = databaseConfig.getCollectionName();
}
//methods etc...
}
DatabaseConfig
类如下:
@ConfigurationProperties(prefix = "database")
@ConstructorBinding
public class DatabaseConfig {
//methods etc...
}
我试图在我的OrderService
类注入模拟如下:
@RunWith(MockitoJUnitRunner.class)
class OrderServiceTest {
@InjectMocks
OrderService orderService;
@Mock
DatabaseConnection dbConnection; // working as expected
@Mock
DatabaseConfig databaseConfig; // giving null pointer
@Mock
DatabaseCollectionConfig databaseCollectionConfig;
@BeforeEach
public void setup() {
MockitoAnnotations.openMocks(this);
when(databaseConfig.getCollections()).thenReturn(databaseCollectionConfig);
when(databaseCollectionConfig.getCollectionName()).thenReturn("myCollection");
}
当我运行我的测试类,我得到:
org.mockito.exceptions.misusing.InjectMocksException:
Cannot instantiate @InjectMocks field named 'OrderService' of type 'class com.my.package.OrderService'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null
问题是,在OrderService
构造函数中,当我调试这一行时,将显示为空:
this.collectionName = databaseConfig.getCollectionName();
如何正确模拟databaseConfig.getCollectionName()
来解决null问题?
不需要使用@InjectMock注释,因为您在服务类中使用的是基于构造函数的注入。请像这样重写测试用例,然后再试一次。
@RunWith(MockitoJUnitRunner.class)
class OrderServiceTest {
OrderService orderService;
@Mock
DatabaseConnection dbConnection; // working as expected
@Mock
DatabaseConfig databaseConfig; // giving null pointer
@Mock
DatabaseCollectionConfig databaseCollectionConfig;
@BeforeEach
public void setup(){
when(databaseConfig.getCollections()).thenReturn(databaseCollectionConfig);
when(databaseCollectionConfig.getCollectionName()).thenReturn("myCollection");
orderService = new OrderService(dbConnection, databaseConfig);
}
}
您可以尝试为该方法创建一个模拟,并创建一个对象实例,而不是使用InjectMocks
注释。
@RunWith(MockitoJUnitRunner.class)
class OrderServiceTest {
OrderService orderService;
@Mock
DatabaseConnection dbConnection; // working as expected
@Mock
DatabaseConfig databaseConfig; // giving null pointer
@Mock
DatabaseCollectionConfig databaseCollectionConfig;
@BeforeEach
public void setup() {
(...)
when(databaseConfig.getCollections()).thenReturn(databaseCollectionConfig);
when(databaseCollectionConfig.getCollectionName()).thenReturn("myCollection");
orderService = new OrderService(dbConnection, databaseConfig);
}
模仿行为,而不是值。@ConfigurationProperties
类只是数据的容器;(一般来说)不做任何事情。使用您的测试值(例如,setCollections(testDatabaseCollectionConfig)
)创建一个真正的new
。