2012-04-18 289 views
0

我有幾個類別:StateProcessor國家。 我想寫一個測試方法StateProcessor.process(State)。 這個方法的邏輯非常簡單,但它包含了很多日誌消息。單元測試和記錄

logger.info(state.getSourse().toString()); 
if (state.getTarget() == Target.A) { 
logger.info(state.getCreationTime()); 
service.doSmth(state); 
} else { 
logger.info(state.getTagret().getName()); 
service.doOtherStff(state); 
} 

我不想真正國家實例傳遞給過程方法,因爲這個類是非常複雜,它需要大量的代碼來構建它的行。所以,我想傳遞Mockito創建的模擬對象。根據主要邏輯,我只需要模擬getTarget()方法。但執行將失敗,NPE處於state.getTagret()。getName()state.getSourse()。toString()。但我不喜歡嘲笑所有這些方法的想法!他們只用於記錄。另外,我不想每次添加日誌消息時都修復測試。

日誌記錄在那裏非常有用,所以我根本不想刪除它。但嘲笑僅用於記錄日誌的方法看起來很奇怪。

我該如何解決這個問題?

+0

難道你不能配置測試環境來切斷所有的'logger.info'消息,同時讓你的dev顯示它們嗎? – 2012-04-18 15:34:18

+0

對不起,我沒有明白你的意思。日誌記錄在當前時間被禁用。但我不能刪除所有這些logger.info行 – NullPointer 2012-04-18 15:39:05

+0

我的意思是什麼第一個回答狀態 – 2012-04-18 16:00:23

回答

1

考慮嘲笑DEEP。這將導致每個方法調用返回一個模擬而不是null並阻止NPE。

Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS); 
+0

這正是我需要的!工作正常!我正在尋找一些魔法,就是這樣! – NullPointer 2012-04-18 16:24:57

0

您可以將所有的日誌記錄調用包含在if (!test) {}塊中並注入測試屬性。

或者您可以將它們放入if (logger.isInfoEnabled()) {}區塊並配置禁用信息的日誌記錄,或者注入一個模擬記錄器,該記錄器返回isInfoEnabled()的假。

但日誌記錄是您的代碼的關鍵部分。所以如果你真的想測試它不會在生產中爆炸,你應該測試生產代碼中的空值,或者證明這些屬性可能永遠不會返回null,並且注入一個不返回null的模擬。 PS:你真的打算在代碼中保留tagretsourse的屬性嗎?

+0

這是不錯的想法包裝日誌與「如果」。但是這會弄亂代碼。代碼片段是捏造的,所以屬性名稱不是真實的。 – NullPointer 2012-04-18 16:28:22

1

你有什麼是經典Law of Demeter侵犯,這是一個教科書案例嘲諷的問題。

作爲一種替代方案,可以考慮將整個State對象記錄在一個位置 - 比如在'if'塊之前 - 並覆蓋toString()方法以輸出您需要查看的所有內容。那麼你不需要對每個領域進行解引用,並模擬每種方法。