2013-07-29 32 views
5

Sử dụng FakeItEasy, làm cách nào để kiểm tra xem phương thức của đối tượng của tôi có gọi phương thức khác trên cùng một đối tượng này không?Sử dụng A.CallTo của FakeItEasy trên một phương thức khác trong cùng một đối tượng

Các thử nghiệm:

[TestMethod] 
public void EatBanana_CallsWillEat() 
{ 
    var banana = new Banana(); 
    var myMonkey = new Monkey(); 

    myMonkey.EatBanana(banana); 

    //this throws an ArgumentException, because myMonkey is a real instance, not a fake 
    A.CallTo(() => myMonkey.WillEat(banana) 
    .MustHaveHappened(); 
} 

The Class:

public class MyMonkey { 
    private readonly IMonkeyRepo _monkeyRepo; 

    public MyMonkey(IMonkeyRepo monkeyRepo) { 
    _monkeyRepo = monkeyRepo; 
    } 

    public void EatBanana(Banana banana) { 
    //make sure the monkey will eat the banana 
    if (!this.WillEat(banana)) { 
     return; 
    } 

    //do things here 
    } 

    public bool WillEat(Banana banana) { 
    return !banana.IsRotten; 
    } 
} 

Tôi mở để gợi ý. Nếu tôi đang đi về điều này tất cả sai, xin vui lòng cho tôi biết.

+2

Đây không thực sự là những gì FIE dành cho, vì tôi hiểu nó. FIE cung cấp các đối tượng giả mạo để mã sản xuất của bạn có thể dễ dàng được chọc và thúc đẩy hơn. Như bạn chỉ ra, bạn không có giả mạo. Theo kinh nghiệm của tôi, loại thử nghiệm này thường không phải là một ý tưởng hay. Lớp MyMonkey của bạn nên là một đơn vị khá độc lập và bạn nên kiểm tra hành vi tổng thể của nó khi được yêu cầu ăn chuối, hơn là lo lắng liệu nó có được gọi là phương pháp riêng của nó hay không. Ví dụ, bạn có thể biết liệu chuối có được ăn dựa trên những manh mối từ những gì xảy ra trong "// làm những việc ở đây" không? –

+0

@BlairConrad trong kịch bản thực tế của tôi, WillEat phức tạp hơn, và có các bài kiểm tra riêng của nó, và đây chỉ là một trong những bài kiểm tra mà EatBanana có. Trong bài kiểm tra này, nếu tôi để EatBanana gọi WillEat thực sự, tôi sẽ không thử nghiệm hai tính năng trong một bài kiểm tra? Sau đó, nếu WillEat thay đổi, nó có thể phá vỡ thử nghiệm đó, đó là tin xấu, phải không? –

+4

Tôi thấy quan điểm của bạn. Đó là khó khăn. Nếu 'WillEat' sống trên một vật thể khác, tất cả chúng ta sẽ thúc giục sự giả mạo của vật thể đó và tiêm nó vào 'MyMonkey' (nghe có vẻ đau đớn). Tất cả những gì tôi thực sự có thể nói là tôi nghĩ rằng vị trí mặc định tốt nhất sẽ là thử nghiệm 'MyMonkey' từ bên ngoài, dựa vào kết quả quan sát của khách hàng. Nhưng, bạn đã suy nghĩ về nó, và đã tìm thấy một giải pháp giúp bạn giảm đau và giảm số lượng các bài kiểm tra cũng như số lượng sẽ phá vỡ cho một. Bạn biết mã tốt nhất, vì vậy nếu nó hoạt động cho bạn ... Tôi chỉ muốn bạn biết về phương án thay thế. –

Trả lời

2

Có thể thực hiện việc này. Nếu phương thức WillEat là ảo - nếu không FakeItEasy sẽ không thể giả mạo nó.

Với sự thay đổi đó, bạn có thể làm điều này:

[TestMethod] 
public void EatBanana_CallsWillEat() 
{ 
    var fakeMonkey = A.Fake<MyMonkey>(); 

    fakeMonkey.EatBanana(new Banana()); 

    A.CallTo(()=>fakeMonkey.WillEat(A<Banana>._)).MustHaveHappened(); 
} 

tôi vẫn không tin đó là một ý tưởng tốt (như tôi ranted trong các ý kiến) - Tôi nghĩ rằng bạn muốn được tốt hơn dựa vào khác hành vi quan sát được, nhưng tôi không quen thuộc với hệ thống của bạn. Nếu bạn nghĩ rằng đây là cách tốt nhất để đi, mã ví dụ sẽ làm việc cho bạn.

3

Tại sao bạn chế nhạo đối tượng thử nghiệm? chính xác nào bạn đang thử nghiệm? Việc xác minh gọi tới số WillEat xảy ra không có giá trị nhỏ. Thông tin gì máy chủ cho người tiêu dùng? Sau khi tất cả, người tiêu dùng không quan tâm cách thức phương pháp được thực hiện. Người tiêu dùng quan tâm những gì là kết quả.

Điều gì xảy ra khi khỉ ăn chuối không bị thối? thử nghiệm của bạn nên trả lời câu hỏi này:

[TestMethod] 
public void EatBanana_CAUSES_WHAT_WhenBananaIsNotRotten() 
{ 
    var repo = A.Fake<IMonkeyRepo>(); 
    var monkey = new Monkey(repo); 
    var freshBanana = new Banana { IsRotten = false }; 

    monkey.EatBanana(freshBanana); 

    // verifications here depend on what you expect from 
    // monkey eating fresh banana 
} 

Lưu ý rằng bạn có thể làm tất cả các loại xác minh để IMonkeyRepo, đó là giả đúng cách và tiêm ở đây.

+0

Điểm tốt. Nếu tôi không chế giễu WillEat, và tôi cho phép EatBanana gọi WillEat thực sự, tôi có thử nghiệm hai tính năng trong một thử nghiệm không?Trong ví dụ này, WillEat là tầm thường, nhưng trong tình hình thực tế của tôi, nó phức tạp hơn, và trả về một đối tượng có nguồn gốc dựa trên các đối số của nó, vì vậy tôi đã tìm ra nó và xác minh nó được gọi là đúng cách. Hiện tại tôi có các bài kiểm tra riêng cho WillEat và một vài bài kiểm tra khác cho EatBanana, bao gồm xác minh rằng repo đã được gọi. Có lẽ tôi đang trở nên quá chi tiết? –

+3

@JoshNoe: hoặc có thể bạn không đủ chi tiết. Nếu 'WillEat' là phức tạp, có lẽ nó nên sống trong lớp riêng của nó? Có lẽ nó có ý nghĩa hơn để trích xuất tính năng này thành * food-evaluator-sort-of-thing * và tiêm nó vào khỉ? Các xét nghiệm * nên * đơn giản - nếu chúng không phải là nó * thường * là một chỉ báo tốt mà thiết kế có thể được xem xét lại. Một lưu ý phụ, tại sao 'Monkey' phụ thuộc vào' IMonkeyRepository'? –

Các vấn đề liên quan