簡體   English   中英

模擬內部實例化對象

[英]Mocking internal instantiated object

我正在編寫一個測試類來測試我的'ImporterService'類。 此服務讀取InputStream並從其數據創建Object。 Object(在本例中為Builder類)在“ImporterService”類中實例化。 要測試我的'ImporterService'類,我需要驗證Builder類的調用。 為此,我想使用Mocking框架,但是如何在'ImporterService'之外創建'Builder'對象的模擬實例?

我的'ImporterService'類的方法如下所示:



    public Builder importFrom(BufferedReader reader) throws IOException {
        String someValue = readFrom(reader);
        Builder builder = new Builder();   // I need to mock this Builder object...
        builder.someMethod(someValue);     // to see of a method is called with the expected value
    }

我正在考慮將Builder類的創建移動到受保護的方法中,我可以在測試設置時覆蓋它。 但是這個解決方案對我來說似乎並不是很好,因為'ImporterService'類正在泄漏一些內部邏輯,並且可以通過我不想要的其他類來覆蓋該方法。

如果您使用任何依賴注入庫(如Spring),您可以將模擬對象而不是構建器注入ImporterService類。 或者你可以用對工廠的調用替換對構造函數的調用,並使用工廠,它會在測試代碼中返回模擬。

是的,您可以按照建議或者:

創建一個Factory類,在其中創建Builder對象並將其分配給reader類。 在您的單元測試中,模擬此工廠並強制它構建您選擇的構建Builder ,您可以在單元測試中檢查方法調用。

以下是使用EasyMock顯示如何實現此目的的示例:

public class Reader{
   private BuilderFactory factory = new BuilderFactory(); // Use production factory by default
   public Builder importFrom(BufferedReader reader) throws IOException {
        String someValue = readFrom(reader);
        Builder builder = factory.buildBuilder();
        builder.someMethod(someValue);     // to see of a method is called with the expected value
    }
}

在您的單元測試中,您執行以下操作:

Reader classUnderTest = new Reader();
BuilderFactory fakeFactory = EasyMock.createNiceMock(BuilderFactory.class);
Builder builder = EasyMock.createMock(Builder.class);
EasyMock.expect(fakeFactory.buildBuilder()).andReturn(builder);
builder.someMethod("value here");
EasyMock.expectLastCall().once();
EasyMock.replay(fakeFactory, builder);
classUnderTest.importFrom(bufferReader);
// Very that all calls were correctly performed on the builder
EasyMock.verify(builder);

假設您正在使用jMockt(我推薦這個模擬框架),您將能夠執行以下操作:

  @Test
    public void testFoo(@Mocked Builder builder) {
        new Expectations() {
            {
                new Builder();
                returns(builder);

                builder.setSomemethod()
                ...
            }
        };

        assertSame(builder,impoertesService.importFrom(...));
    }

一些模擬框架(如PowerMock)可以模擬對象的構造。

您可以將功能簽名更改為以下內容:

public Builder importFrom(BufferedReader reader, Builder builder) throws IOException {

通過這樣做,您可以從您的測試用例傳遞任何虛擬實現。 這是依賴注入的一種方式。

依賴注入的想法是要求所有依賴項,如果類/函數執行此操作,則代碼變得高度可測試。

暫無
暫無

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

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