Java:将带有Inject批注的类junit [英] Java: Junit a class with Inject annotation

查看:100
本文介绍了Java:将带有Inject批注的类junit的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@Singleton
public class RealWorkWindow implements WorkWindow {

    @Inject private Factory myFactory;

    public RealWorkWindow (
            LongSupplier longSupplier
    ) {
        defaultWindow = myFactory.create(() -> 1000L);
        workWindow = myFactory.create(longSupplier);
    } 
    ...

如您所见,我正在注入工厂类(通过FactoryModuleBuilder注入)

As you can see I am Injecting a factory class (injected via FactoryModuleBuilder)

测试代码

@Test
public class RealWorkWindowTest {
    private RealWorkWindow testWindow;

    @BeforeMethod
    void setup() {
        MockitoAnnotations.initMocks(this);

        testWindow = spy(new RealWorkWindow(() -> 1L));
    }

Factory.py

Factory.py

public interface RealWorkWindowFactory {
    RealWorkWindowFactory create(LongSupplier longSupplier);
}

模块

install(new FactoryModuleBuilder()
                        .implement(WorkWindow.class, RealWorkWindow.class)
                        .build(RealWorkWindowFactory.class));

当我运行测试RealWorkWindowTest时,由于NPE测试失败,表明工厂不存在,这是有道理的,因为我认为注入不会运行.

When I run the test RealWorkWindowTest the test fails with NPE that factory does not exists, which makes sense since I dont think injection runs.

如何在junit中使用Injection进行测试?或正确模拟?

How can I test with Injection in junit? or mock properly?

与问题类似,描述于 https://mhaligowski.github.io/blog/2014/05/30/mockito-with-both-constructor-and-field-injection.html

但是我遇到的问题是使用了 IN 构造函数,因此在实例化测试对象时它仍然为null(因为我还没有调用Mockito.init)

But the problem that I have is that mock is used IN constructor so it's still a null when instantiate the test object (because i have not called Mockito.init yet)

推荐答案

使用@Assisted注入时使用构造函数注入

Guice的辅助注入Wiki页面提到:

Use constructor injection when using @Assisted injection

Guice's Assisted Injection wiki page mentions:

AssistedInject自动生成工厂类的实现.要使用它,请注释实现类的构造函数和注入器不知道的字段:

AssistedInject generates an implementation of the factory class automatically. To use it, annotate the implementation class' constructor and the fields that aren't known by the injector:

后来:

AssistedInject将create()方法的参数映射到实现类的构造函数中的相应@Assisted参数. 对于其他构造函数参数,它要求常规的Injector提供值.

由于它们仅在那时可用,因此Guice只会在构造函数调用之后 注入字段.这为您提供了一个事实,即您必须使用构造函数注入,并且没有其他机制(除非您具有允许@PostConstruct或类似功能的扩展名).

As they are only available at that time, Guice will only inject fields after the constructor call. This translates for you in the fact that you must use the constructor injection, and no other mechanism (unless you have an extension that allows @PostConstruct or similar).

所以让我们根据它重写代码.编写您的RealWorkWindow,如下所示:

So let's rewrite your code according to that. Write your RealWorkWindow as follow:

@Singleton
public class RealWorkWindow implements WorkWindow {

  private final WorkWindow defaultWindow;
  private final WorkWindow workWindow;

  @Inject
  public RealWorkWindow(Factory myFactory, @Assisted LongSupplier longSupplier) {
    defaultWindow = myFactory.create(() -> 1000L);
    workWindow = myFactory.create(longSupplier);
  }

}

您的代码可以如下进行测试:

Your code can then become testable as follows:

@RunWith(MockitoJunitRunner.class)
public class RealWorkWindowTest {

  @Mock
  Factory myFactory;

  @Mock
  WorkWindow defaultWindow;

  @Mock
  WorkWindow workWindow;

  RealWorkWindow realWorkWindow;

  @BeforeEach
  void setup() {
    when(myFactory.create(any(LongSupplier.class)))
        .thenReturn(defaultWindow) // First call
        .thenReturn(workWindow);   // Second call
    realWorkWindow = new RealWorkWindow(myFactory, () -> 1000L);
  }

}

这篇关于Java:将带有Inject批注的类junit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆