Java:Junit 一个带有 Inject 注释的类


@Singleton
public class RealWorkWindow implements WorkWindow {
@Inject private Factory myFactory;
public RealWorkWindow (
LongSupplier longSupplier
) {
defaultWindow = myFactory.create(() -> 1000L);
workWindow = myFactory.create(longSupplier);
} 
...

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

测试代码

@Test
public class RealWorkWindowTest {
private RealWorkWindow testWindow;
@BeforeMethod
void setup() {
MockitoAnnotations.initMocks(this);
testWindow = spy(new RealWorkWindow(() -> 1L));
}

Factory.py

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

模块

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

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

我怎样才能在 junit 中使用注射进行测试? 还是正确模拟?

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

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

如果您使用MockitoJUnitRunner,您可以使用@Mock为工厂创建模拟并注入它。

@RunWith(MockitoJUnitRunner.class)
public class MyTest {
@Mock
private Factory myFactory;
@InjectMocks
private RealWorkWindow realWorkWindow;
@Test
public void testSomething() {
when(myFactory.create(/* insert param here */)).thenReturn(/* insert return value here */);
/* perform your test */
}
}

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

Guice的辅助注射维基页面提到:

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

后来:

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

由于它们仅在那时可用,因此 Guice 只会在构造函数调用注入字段。这意味着您必须使用构造函数注入,而不是其他机制(除非您有允许@PostConstruct或类似机制的扩展)。

因此,让我们根据此重写代码。按如下方式编写您的RealWorkWindow

@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);
}
}

然后,您的代码可以变得可测试,如下所示:

@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);
}
}

相关内容

  • 没有找到相关文章

最新更新