如何使用 Mockito 注入字段而不在构造函数中指定它们?

Who*_*ing 5 java dependency-injection mockito

我有一个类(PriceSetter),我正在使用 Mockito 进行测试,并且该类具有内部依赖项(数据库)。我想模拟这个内部依赖项,然后将其注入到类中,但是我的构造函数中没有指定依赖项。因此,Mockito 自动尝试进行构造函数注入,并且依赖项永远不会被注入。

我尝试在我的数据库对象上使用@Mock,在我的PriceSetter类上使用@InjectMocks,但是Mockito自动调用构造函数,并且它无法注入我的数据库模拟,因为数据库没有传递到构造函数中。

class PriceSetter {
    private Table priceTable;

    public PriceSetter(Dependency d1, Dependency d2) {
        this.d1 = d1;
        this.d2 = d2;
    }
}

@RunWith(MockitoJUnitRunner.class)
class PriceSetterTest{
    @InjectMocks
    private PriceSetter setter;

    @Mock Table priceTable;
    @Mock Dependency d1;
    @Mock Dependency d2;

    @Test
    public void someTestMethod() {
        when(priceTable.getItem(any())).thenReturn(Specified item);
        setter.priceTable.getItem("item"); -> Doesn't return item specified by mocked behavior
    }
}
Run Code Online (Sandbox Code Playgroud)

我预计priceTable会被注射,但没有被注射。只有d1和d2是通过构造函数注入注入的。

Mar*_*ers 3

@InjectMocks只会执行构造函数注入或属性注入之一,而不是两者都执行。

Mockito 将尝试通过构造函数注入、setter 注入或属性注入按顺序注入模拟...

你总是可以做

@Before
public void setUp() {
   setter.setPriceTable(priceTable);
}
Run Code Online (Sandbox Code Playgroud)

或者你的桌子应该接线。然而,最简洁的设计通常是统一依赖注入方法,将所有内容注入到构造函数中。由于@InjectMocks将选择最大的构造函数并在私有或包私有构造函数上工作,因此一种选择是添加构造函数重载:

class PriceSetter {
    private Table priceTable;

    public PriceSetter(Dependency d1, Dependency d2) {
        this(d1, d2, new DefaultPriceTable());
    }

    PriceSetter(Dependency d1, Dependency d2, Table priceTable) {
        this.d1 = d1;
        this.d2 = d2;
        this.priceTable = priceTable;
    }

}
Run Code Online (Sandbox Code Playgroud)