Ale*_*noy 19 java junit guice code-injection
使用Guice,在每个JUnit测试类中获取一个新的注入器是一个好习惯,因为每个测试类应该是独立的吗?
Mic*_*mlk 36
你应该避免在单元测试中使用Guice,因为每个测试应该足够小,以至于手动DI是可管理的.通过在单元测试中使用Guice(或任何DI),您隐藏了一个警告,表明您的班级正在变得越来越重,承担了太多的责任.
为了测试引导程序代码和集成测试,然后是为每个测试创建一个不同的注入器.
Joe*_*ams 27
万一有人偶然发现这个问题,并希望看到如何从单元测试中获取Guice注释,请从下面的基类扩展测试并调用 injector.injectMembers(this);
public class TestBase {
protected Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(HelloService.class);
}
});
@Before
public void setup () {
injector.injectMembers(this);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的测试可以得到一个注入HelloService这样的
public class HelloServiceTest extends TestBase {
@Inject
HelloService service;
@Test
public void testService() throws Exception {
//Do testing here
}
}
Run Code Online (Sandbox Code Playgroud)
Adi*_*ing 10
我认为使用DI会使单元测试代码更简单,我总是使用DI进行单元测试以及集成测试.
没有DI,一切都很难编码.要么使用Guice Inject or Spring Autowired.比如我的测试代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/application-context.xml")
public class When_inexists_user_disabled {
@Autowired
IRegistrationService registrationService;
private int userId;
@Before
public void setUp() {
Logger.getRootLogger().setLevel(Level.INFO);
Logger.getLogger("org.springframework").setLevel(Level.WARN);
BasicConfigurator.configure();
userId = 999;
}
@Test(expected=UserNotFoundException.class)
public void user_should_have_disabled() throws UserNotFoundException {
registrationService.disable(userId);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
这取决于所使用的 JUnit 版本。我们的团队已经成功地使用了 Junit4,现在正在研究 JUnit5。
在 Junit5 中,我们使用扩展。
public class InjectionPoint implements BeforeTestExecutionCallback {
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
List<Module> modules = Lists.newArrayList(new ConfigurationModule());
Optional<Object> test = context.getTestInstance();
if (test.isPresent()) {
RequiresInjection requiresInjection = test.get().getClass().getAnnotation(RequiresInjection.class);
if (requiresInjection != null) {
for (Class c : requiresInjection.values()) {
modules.add((Module) c.newInstance());
}
}
Module aggregate = Modules.combine(modules);
Injector injector = Guice.createInjector(aggregate);
injector.injectMembers(test.get());
getStore(context).put(injector.getClass(), injector);
}
}
private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass()));
}
}
Run Code Online (Sandbox Code Playgroud)
然后每个测试使用 RequiresInjection 注解,它可以接受一组内部模块进行聚合,或者不使用默认值。
@RequiresInjection
public class Junit5InjectWithoutModuleTest {
@Inject
private TestEnvironment environment;
@Test
public void shouldAccessFromOuterModule() {
assertThat(environment).isNotNull();
}
}
Run Code Online (Sandbox Code Playgroud)
这是注释:
@ExtendWith(InjectionPoint.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
public @interface RequiresInjection {
Class<? extends Module>[] values() default {};
}
Run Code Online (Sandbox Code Playgroud)
JUnit5 对我来说仍然是新手,所以我可能正在研究模板,但到目前为止,扩展似乎可以解决问题。
对于 JUnit4,我们使用类似的方法,不同之处在于注入发生在我们自定义测试运行器的 createTest 方法中,然后每个测试实现一个 RequiresInjection 接口,该接口具有“getModule”方法。
我可能也应该对 TestNG 大喊大叫,因为 Guice 支持是内置的。 使用就像这样简单:
@Guice({SomeObjectModule.class})
public class MyTest {
@Inject
SomeObject someObject;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
46912 次 |
| 最近记录: |