2014-03-13 23 views
0

我有一個域名服務如何正確地單元測試域服務?

public class BlobService{ 
    private FooRepository repo; 
    public BlobService(FooRepository repo){ 
     this.repo = repo; 
    } 
    public void DoSomething(int id1,int id2){ 
     var foo1 = repo.Get(id1); 
     var foo2 = repo.Get(id2); 
     var valueSomething = foo1.GetValueSomething(); 
     foo2.SetValueSomething(valueSomething); 
     repo.Save(foo2); 
     DomainEvent.Raise(new ValueSomethingChanged(foo2)); 
    } 
} 

這裏,方法

  • repo.Get,repo.Save通過集成測試(因爲後面的RDBMS)
  • GetValueSomething,SetValueSomething測試並通過單元測試提高

那麼我的單元測試BlobService會是什麼樣子?

  • 嘲笑回購,foo1和foo2並檢查好方法被稱爲。 DomainEvent是靜態的,但真的很簡單
  • 做的是集成測試:發送真正的repo實現,請求它並檢查foo2值。
  • 別的東西

+0

嘿雷米。如果我的答案是令人滿意的,你能否贊成並將其標記爲答案?謝謝! –

回答

1

如果調用回購方法,我在測試中看不到任何價值。當我們測試一個打算與某個外部系統進行交互的組件時,使用這個mock特性是很有用的。這裏不是這種情況。

無論您使用什麼類型的測試,都應該有AAA結構。安排 - 準備一些測試數據/狀態。行動 - 致電您的服務。斷言 - 驗證結果(最終狀態)是否正確。您使用域事件 - 這意味着如果正確事件發生,也會進行測試。如果您使用事件採購 - 您會將事件安排爲播放事件,聲明部分僅包含檢查事件。

集成測試比單元測試慢。如果持久性泄露到域中或相反,則需要它們。例如,當您依賴ORM的延遲加載功能(順便說一句,這不是非常類似DDD的)或使用存儲過程。

好了,不要以爲太快,它不漏;)

0

這些都是我一路上學到了一些相關的測試DDD原則:

  • 你需要的唯一的事測試是的行爲,而不是狀態。(如果您檢查NServiceBus處理程序/傳奇測試如何工作,則由Udi Dahan支持。)
  • 快速運行測試非常關鍵。慢速運行的集成測試是不值得的,因爲它們很慢並且容易破損。維護的努力不值得我項目的回報。

(同樣,這些都是具體到我的項目 - 情況因人而異。)

所以考慮到這一點,這裏就是我會測試你的類。 (請注意,我殺了靜態DomainEvents類,因爲它使測試的方式在我的經驗更容易IBus取代它。):

public class BlobService 
{ 
    private IBus _bus; 
    private IFooRepository _repo; 

    public BlobService(IBus bus, IFooRepository repo) 
    { 
     _bus = bus; 
     _repo = repo; 
    } 

    public void DoSomething(int id1, int id2) 
    { 
     var foo1 = _repo.Get(id1); 
     var foo2 = _repo.Get(id2); 
     var valueSomething = foo1.GetValueSomething(); 
     foo2.SetValueSomething(valueSomething); 
     _repo.Save(foo2); 

     _bus.Publish(new ValueSomethingChanged(foo2)); 
    } 
} 

[TestFixture] 
public class BlobRepositoryTests 
{ 
    [Test] 
    public void DoSomething_RaisesValueSomethingChanged() 
    { 
     // Arrange: 
     var bus = new MockBus(); // just stores the events in a publicly accessible list 
     var repo = new MockBlobRepository(); // does whatever you need it to do (or use Moq, etc) 
     var service = new BlobService(bus, repo); 

     // Act: 
     service.DoSomething(1, 2); 

     // Assert: 
     var @event = bus.Events.OfType<ValueSomethingChanged>().Single(); 
     Assert.That(() => @event.Property1, Is.EqualTo(someExpectedValue)); 
     Assert.That(() => @event.Property2, Is.EqualTo(someOtherExpectedValue)); 
    } 
} 
+0

那麼如何測試該服務調用SetValueSomething? –

+0

它不需要測試。這是一個內部實現細節。假設您發現(像我一樣),甚至沒有必要擁有這些存儲庫和域對象,並且您可以直接通過ORM訪問數據庫。如果發生這種情況,那麼當系統的實際業務邏輯沒有改變時,你將不得不對測試進行重大的重構。這就是爲什麼你不應該測試它。 –

+0

那麼,你寫的測試是唯一一個你會做的? –