英文:
Bad state: GetIt: Object/factory with type <> is not registered inside GetIt
问题
I am trying to use dependency injection with the get_it
package in order to make unit tests.
我正在尝试使用get_it
包进行依赖注入,以便进行单元测试。
I am using these dependencies:
我正在使用以下依赖项:
get_it: ^7.6.0
injectable_generator: ^2.1.6
My main
function looks like this:
我的main
函数如下所示:
void main(List<String> args) async {
// Configure injection
await setup(Env.test);
await getIt.allReady();
// [...]
}
I wait for the setup with the test
environment, and I wait for it to be allReady
.
我等待使用test
环境进行设置,并等待它准备好。
The file uses injection.dart
, which contains the setup()
function:
该文件使用包含setup()
函数的injection.dart
:
GetIt getIt = GetIt.instance;
@InjectableInit(preferRelativeImports: false)
setup(String env) {
getIt.init();
if (env == Env.test) {
getIt.registerLazySingleton<IAuthRepository>(() => TestAuthRepository());
} else {
getIt.registerLazySingleton<IAuthRepository>(() => AuthRepository());
}
}
abstract class Env {
static const prod = 'prod';
static const test = 'test';
}
As you can see, I want to use AuthRepository
for production (which will call a database) or TestAuthRepository
for unit tests (which will not call the database).
正如你所看到的,我想在生产中使用AuthRepository
(它将调用数据库)或在单元测试中使用TestAuthRepository
(它不会调用数据库)。
I have declared these classes in a file called auth_repository.dart
:
我在名为auth_repository.dart
的文件中声明了这些类:
abstract class IAuthRepository {
Future<int> createNewUser({
required String login,
required String email,
required String password,
});
}
@Injectable(as: IAuthRepository, env: [Env.prod])
class AuthRepository extends BaseRepository implements IAuthRepository {
@override
Future<int> createNewUser({
required String login,
required String email,
required String password,
}) async {
try {
final connection = await getDatabaseConnection();
// ...(进行数据库调用)...
return 1;
} catch (exception) {
print(exception);
return -1;
}
}
}
@Injectable(as: IAuthRepository, env: [Env.test])
class TestAuthRepository extends BaseRepository implements IAuthRepository {
@override
Future<int> createNewUser({
required String login,
required String email,
required String password,
}) {
return Future.value(2);
}
}
For now, the testing function createNewUser
will only return 2.
目前,测试函数createNewUser
将只返回2。
I am launching my test here:
我在这里启动我的测试:
void main() {
AuthController authController = AuthController();
test('Registration success', () async {
int response = await authController.register(
login: 'test',
email: 'email@mail.com',
password: 'Testing193!',
passwordConfirmation: 'Testing193!',
);
expect(response, 1);
});
// ...
}
This test calls the authController.register()
method, which is defined as follows:
这个测试调用了authController.register()
方法,其定义如下:
Future<int> register({
required String login,
required String email,
required String password,
required String passwordConfirmation,
}) async {
// [...]
IAuthRepository authRepository = getIt.get<IAuthRepository>();
return await authRepository.createNewUser(
login: login,
email: email,
password: password,
);
}
I try to retrieve an IAuthRepository
instance with getIt
.
我尝试使用getIt
获取一个IAuthRepository
实例。
However, when I launch my tests, I get this error:
然而,当我运行我的测试时,我收到以下错误消息:
00:00 +0 -1: Registration success [E]
Bad state: GetIt: Object/factory with type IAuthRepository is not registered inside GetIt.
(Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;
Did you forget to register it?)
package:get_it/get_it_impl.dart 12:19 throwIfNot
package:get_it/get_it_impl.dart 395:5 _GetItImplementation._findFactoryByNameAndType
package:get_it/get_it_impl.dart 423:29 _GetItImplementation.get
package:toast/controllers/auth_controller.dart 31:44 AuthController.register
test/controllers/auth_controller_test.dart 23:41 main.<fn>
I thought I registered my IAuthRepository
class; however, it does not work. How can I register it?
我以为我已经注册了我的IAuthRepository
类,但是它不起作用。我该如何注册它?
英文:
I am trying to use dependency injection with get_it
package, in order to make unit tests.
I am using these dependencies :
get_it: ^7.6.0
injectable_generator: ^2.1.6
My main
function looks like this :
void main(List<String> args) async {
// Configure injection
await setup(Env.test);
await getIt.allReady();
// [...]
}
I wait for the setup with the test
environment, and I wait for it to be allReady
.
The file uses injection.dart
, which contains the setup()
function :
GetIt getIt = GetIt.instance;
@InjectableInit(preferRelativeImports: false)
setup(String env) {
getIt.init();
if (env == Env.test) {
getIt.registerLazySingleton<IAuthRepository>(() => TestAuthRepository());
} else {
getIt.registerLazySingleton<IAuthRepository>(() => AuthRepository());
}
}
abstract class Env {
// static const dev = 'dev';
static const prod = 'prod';
static const test = 'test';
}
As you can see, I want to use AuthRepository
for production (will call a database), or TestAuthRepository
for unit tests (will not call the database).
I declared theses class here, in a file auth_repository.dart
:
abstract class IAuthRepository {
Future<int> createNewUser({
required String login,
required String email,
required String password,
});
}
@Injectable(as: IAuthRepository, env: [Env.prod])
class AuthRepository extends BaseRepository implements IAuthRepository {
@override
Future<int> createNewUser({
required String login,
required String email,
required String password,
}) async {
try {
final connection = await getDatabaseConnection();
// ... (make the database call) ...
return 1;
} catch (exception) {
print(exception);
return -1;
}
}
}
@Injectable(as: IAuthRepository, env: [Env.test])
class TestAuthRepository extends BaseRepository implements IAuthRepository {
@override
Future<int> createNewUser({required String login, required String email, required String password}) {
return Future.value(2);
}
}
For now, the testing function createNewUser
will only return 2.
I am launching my test here :
void main() {
AuthController authController = AuthController();
test('Registration success', () async {
int response = await authController.register(
login: 'test',
email: 'email@mail.com',
password: 'Testing193!',
passwordConfirmation: 'Testing193!',
);
expect(response, 1);
});
// ...
}
This test calls for authController.register()
, which is here :
Future<int> register({
required String login,
required String email,
required String password,
required String passwordConfirmation,
}) async {
// [...]
// IAuthRepository authRepository = getIt<IAuthRepository>();
IAuthRepository authRepository = getIt.get<IAuthRepository>();
return await authRepository.createNewUser(
login: login,
email: email,
password: password,
);
}
I try to retrieve an IAuthRepository
instance with getIt
.
However, when I am launching my tests, I get this error :
00:00 +0 -1: Registration success [E]
Bad state: GetIt: Object/factory with type IAuthRepository is not registered inside GetIt.
(Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;
Did you forget to register it?)
package:get_it/get_it_impl.dart 12:19 throwIfNot
package:get_it/get_it_impl.dart 395:5 _GetItImplementation._findFactoryByNameAndType
package:get_it/get_it_impl.dart 423:29 _GetItImplementation.get
package:toast/controllers/auth_controller.dart 31:44 AuthController.register
test/controllers/auth_controller_test.dart 23:41 main.<fn>
I thought I registered my IAuthRepository
class, however it does not work. How can I register it ?
答案1
得分: 1
Here is the translated content:
我终于让它工作了。
问题是这样的:setup()
函数注册了我所需的所有类实现,但它在 main()
函数中被调用(是的,这是我自己的疏忽...)。
然而,由于单元测试是针对每个类单独启动的,因此 main()
函数从未被调用。
所以,我的测试现在看起来像这样:
void main() {
setUpAll(() {
setupGetIt(Env.test);
});
tearDownAll(() {
unregisterGetIt();
});
AuthController authController = AuthController();
test('Registration success', () async {
int response = await authController.register(
login: 'test',
email: 'email@mail.com',
password: 'Testing193!',
passwordConfirmation: 'Testing193!',
);
expect(response, 1);
});
}
setupGetIt()
函数与 setup()
相同(我将其重命名以更清晰),它负责注册我需要的每个类。
我在 setUpAll()
函数中调用它,以便在所有测试之前注册它。
请注意,我还添加了一个 unregisterGetIt()
函数,它基本上只调用 getIt.reset()
来注销每个已注册的类。它在 tearDownAll()
中调用,这在所有测试之后被调用。
我还删除了我实现的类顶部的所有 @Injectable()
注释,因为它们不再需要。
英文:
I finally made it work.
Here was the problem : The setup()
function, which registered all the class implementations I needed, was called in the main()
function (yes, that IS silly from me...).
However, as unit tests are launched specifically to each class, the main()
function was never invoked.
So, my test now looks like this :
void main() {
setUpAll(() {
setupGetIt(Env.test);
});
tearDownAll(() {
unregisterGetIt();
});
AuthController authController = AuthController();
test('Registration success', () async {
int response = await authController.register(
login: 'test',
email: 'email@mail.com',
password: 'Testing193!',
passwordConfirmation: 'Testing193!',
);
expect(response, 1);
});
}
The setupGetIt()
function is the same as setup()
(I renamed it to be more clear), it takes care of registering every class I need.
I call it in a setUpAll()
function, in order to register it before all the tests.
Note that I also added a unregisterGetIt()
function, which basically only calls getIt.reset()
to unregister every registered class. It is called in tearDownAll()
, which is called after all tests.
I also removed all the @Injectable()
annotation on top of my implemented class, as they are not needed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论