簡體   English   中英

如何為Dagger注入類的模擬對象(vs接口)

[英]How to inject mocks for class (vs interface) for Dagger

首先,我正在嘗試提出一些合理的方法來在Android上進行單元測試。 我主要關心POJO對象。

在我以前的項目中,我只是通過構造函數注入了所有依賴項。 我在單元測試中創建了模擬,並通過構造函數注入了這些模擬。 缺點是龐大的構造函數,需要通過多層代碼傳遞參數。

顯而易見的解決方案是依賴注入框架。 我看了看其中一些適用於Android的軟件,並決定使用Dagger。 我弄清楚了,並更新了我的應用程序以使用它。

現在,我想更新單元測試,並且不確定如何更改objectGraph以使用模擬(相對於真實類)。

我看到了這篇文章: https ://gist.github.com/adelnizamutdinov/7483963但是,它僅顯示為@Provideds注釋注入模擬。 尚不清楚如何為類注入模擬(當您未在模塊中提供方法時)

更新1(至Eugen Martynov)

基於Dagger文檔:

默認情況下,Dagger通過構造如上所述的請求類型的實例來滿足每個依賴關系。 當您請求CoffeeMaker時,它將通過調用新的CoffeeMaker()並設置其可注入字段來獲得一個。

但是@Inject並非在所有地方都有效:

接口無法構建。 不能注釋第三方類。 必須配置可配置對象!

對於@Inject不足或不方便的這些情況,請使用帶有@Provides注釋的方法>來滿足依賴性。 方法的返回類型定義了它滿足的依賴關系。

因此,看起來無需@Provides就可以滿足依賴關系。 但是,僅用於注入類(與接口)。

更新2

我的情況如下:

public class Bar {

    @Inject
    Bar() {
    }

    public void doSomethingElse() {
    }
}

public class Foo {

    @Inject
    Bar bar;

    public void doSomething() {
        bar.doSomethingElse();
    }
}

public class FooTest
{

    @Test
    void test_doSomething()
    {
         // I want to create a mock of Bar here and inject it to foo
         // so I can replace all dependencies with mocks before calling 
         // class under test

         foo.doSomething();

    }

}

Dagger將負責注入@Inject注釋的類,而無需您采取任何進一步的措施。 但是,如果您想控制類的創建方式,您只需要在其中一個模塊中添加@Provide方法,就您的情況而言,最好是一個Test模塊,然后自己創建。

默認情況下,如果您的類由Dagger注入而沒有任何干預,則只需返回值“ DEFAULT”

public class MyClass {

    @Inject
    MyClass() {

    }

    public String getValue() {
        return "DEFAULT";
    }
}

您的測試模塊之一中的某個位置

@Provide
MyClass provideMyClass() {
    return Mockito.mock(MyClass.class)
}

然后在進行測試時

@Inject
MyClass myClass;

// code here to actually do the injection

Mockito.when(myClass.getValue()).thenReturn("MOCK");

myClass.getValue(); // Should return "MOCK" instead of "DEFAULT"

編輯:在與@Victor討論之后,這是我建議他可以實現的目標,但是他已經構建了一個小型現場注入工具來直接實現這一目標。 這是代碼,以防其他人使用。

public class FooTest {

    @Mock
    private Bar mockBar;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void useDaggerModuleWithMock() {
        ObjectGraph objectGraph = ObjectGraph.create(new FooMockedTestModule());

        when(mockBar.doSomethingElse()).thenReturn("MOCK");

        Foo foo = new Foo();
        objectGraph.inject(foo);

        assertThat(foo.doSomething(), is("MOCK"));
    }

    @Module(injects = Foo.class)
    public class FooMockedTestModule {
        // We now take advantage of the module and provide our own implementation of the Bar class instead of letting
        // Dagger do the instance creation itself.
        @Provides
        Bar provideMockBar() {
            return mockBar;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM