2011-12-15 117 views
5

我在寫一個測試類來測試我的'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 
    } 
 

我在想移動的生成器類的創建成一個受保護的方法,我可以在測試的設置覆蓋。但是這個解決方案對我來說似乎不是很好,因爲'ImporterService'類泄漏了一些內部邏輯,並且可以用其他我不想要的類重寫方法。

回答

2

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

+0

如果使用好的模擬框架,你不需要在你的單元測試的另一個DI框架中。除非你正在測試你的佈線 – 2011-12-15 09:48:50

0

假設你正在使用jMockt(我本電子書籍模擬框架),你將能夠做到以下幾點:

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

       builder.setSomemethod() 
       ... 
      } 
     }; 

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

有些嘲弄的框架,例如PowerMock可以模擬對象的構造。通過這樣做

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

您可以通過從測試情況下,任何虛擬實現:

0

你可以改變函數簽名這樣的事情。這是依賴注入的一種方式。

依賴注入的想法是要求所有的依賴關係,如果一個類/函數這樣做,代碼變得高度可測試。

1

是的,你可以或做如你所說:

創建一個用於創建對象Builder,並將其分配給讀取器類的工廠類。在你的單元測試中,模擬這個工廠並強制它建立一個你選擇的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);