2015-07-21 62 views
0

我有一個對象,它在異步接收到一些消息更改狀態後(內部線程更改狀態)。狀態改變後,我想測試一些行爲。測試併發代碼的行爲

所以基本上我需要做的是這樣的:

  1. 創建對象
  2. 發送消息到對象
  3. 等待狀態改變
  4. 測試行爲

然而,國家是私人而不是暴露。

有沒有一個優雅的解決方案,這不需要暴露狀態?

如果沒有 - 是否需要更改主代碼才能使其更具可測性?

+0

可能有一種優雅的方式來通過行爲表示狀態變化。如果你能詳細說明你希望測試的行爲,這將有所幫助。你期望有多少種可能的行爲?例如,它是否會在狀態改變之前返回0,之後是1? – NBartley

+0

正在測試的實際行爲並不重要。重點是它只能在狀態改變後才能被測試,否則測試是沒有意義的。 – traveh

回答

-1

如果狀態爲私有狀態,則只能在其自己的類中訪問(https://docs.oracle.com/javase/tutorial/java/javaOO/variables.html),這意味着無法在不修改類的情況下從新創建的對象中獲取狀態。
現在,無論是合理的修改,以做一些測試類是高達幾個因素:

  • 有多少人對代碼的工作?
  • 有多少人已經在使用該代碼的以前版本?
  • 如果將狀態變量更改爲public並添加getter方法,您將面臨的完整性問題。

所以當然我不能告訴你,如果它是合理的,並無須詳細瞭解軟件的組織。
我希望這個簡短的答案可以幫助你至少澄清問題。

-1

假設您有權這樣做,您可以通過Reflection訪問相關的專用字段。

Foo bar = new Foo(); 
    bar.setValue(true); 

    Field field = Foo.class.getDeclaredField("value"); 
    field.setAccessible(true); 
    Object value = field.get(bar); 

這將得到存儲在類中的私有變量的值。

這是非常醜陋的,你可能不應該這樣做,但如果你真的需要避免改變你正在測試的類,那麼它應該做的伎倆。

+0

我很清楚有很多醜陋的解決方案。我的問題是,如果有一個*優雅的解決方案*,而不是一個醜陋的... – traveh

+0

沒有修改你正在測試的類,這是你將得到最優雅。測試課是我甚至建議這樣做的少數幾個地方之一。因爲這是一個可行的答案,所以對我來說投票似乎很難。 –

+0

這就是我所懷疑的,爲什麼我問了問題的第二部分。我最初的想法是將狀態改爲受保護的,從類繼承,並使用繼承的類進行測試,但它讓我覺得這樣做有些激進(尤其是改變對每個度量應該是私有的狀態的訪問除了測試的緣故)。但我想沒有好的選擇。 – traveh

1

測試異步代碼的一般模式是阻止主測試線程,而不是在解除主測試線程之前執行的異步回調中聲明某些內容。下面是一個使用示例ConcurrentUnit

final Waiter waiter = new Waiter(); 

bus.registerMessageHandler(message -> { 
    waiter.assertEquals(message.body(), "foo"); 
    waiter.resume(); 
}); 

waiter.await(5000); 

此測試會創建一個等待5秒鐘的服務員。根據消息總線註冊的回調將在單獨的線程中執行斷言,然後才能恢復服務器,以便測試可以完成。

這個問題顯然需要能夠將某種回調/處理程序插入到應用程序中。如果您只是在等待某個狀態發生變化,而您完全沒有察覺到狀態,那麼您可以做的很多事情來斷言狀態發生變化。