2012-07-21 29 views
5

Giả sử tôi có tổ chức sau đây:Mocking Guid.NewGuid()

public class User 
{ 
    public int Id { get; set; } 
    public string Username { get; set; } 
    public Guid UserGuid { get; set; } 
    public Guid ConfirmationGuid { get; set; } 
} 

Và phương pháp giao diện sau:

void CreateUser(string username); 

Một phần của việc thực hiện nên tạo hai GUID mới: một cho UserGuid, và một cho ConfirmationGuid. Họ nên làm điều này bằng cách đặt các giá trị thành Guid.NewGuid().

Tôi đã đã trừu tượng hóa Guid.NewGuid() sử dụng một giao diện:

public interface IGuidService 
{ 
    Guid NewGuid(); 
} 

Vì vậy, tôi có thể dễ dàng chế nhạo này khi chỉ có một mới GUID là cần thiết. Nhưng tôi không chắc chắn làm thế nào để giả lập hai cuộc gọi khác nhau cho cùng một phương pháp, từ bên trong một phương pháp, sao cho chúng trả về các giá trị khác nhau.

Trả lời

9

Nếu bạn đang sử dụng Moq, bạn có thể sử dụng:

mockGuidService.SetupSequence(gs => gs.NewGuid()) 
    .Returns(...some value here...) 
    .Returns(...another value here...); 

Tôi cho rằng bạn cũng có thể làm như sau:

mockGuidService.Setup(gs => gs.NewGuid()) 
    .Returns(() => ...compute a value here...); 

Tuy nhiên, trừ khi bạn đang chỉ cung cấp một giá trị ngẫu nhiên trong sự trở lại chức năng, kiến ​​thức về trật tự vẫn có vẻ quan trọng.

+0

Nhưng điều này không giả định rằng tôi đang đặt thuộc tính trong quá trình triển khai theo một chuỗi nhất định? Điều này không phải là mối quan tâm của bài kiểm tra của tôi? Nói cách khác, các trường này có thể được đặt theo thứ tự bất kỳ, và nếu vì một lý do nào đó tôi thay đổi thứ tự này mà không cập nhật các bài kiểm tra của tôi, các bài kiểm tra của tôi lý tưởng vẫn nên vượt qua. –

+0

Vâng ... bạn đang đi vào trạng thái so với thử nghiệm hành vi một chút. Tôi không chắc chắn làm thế nào để trả lời câu hỏi mà không đưa ra giả định về kiến ​​thức về thứ tự cuộc gọi. –

+3

Nếu tôi hiểu chính xác, bạn không muốn có 'Assert.AreEqual (guid1, user.UserGuid); Assert.AreEqual (guid2, user.ConfirmationGuid); 'thất bại nếu bạn thay đổi thứ tự gán. Thay vào đó, bạn nên sử dụng một số loại bộ sưu tập khẳng định rằng độc lập với thứ tự (có sẵn trong cả nunit và mstest): 'CollectionAssert.AreEquivalent (new [] {guid1, guid2}, new [] {user.UserGuid, user.ConfirmationGuid}) ; ' –

4

Nếu bạn không thể sử dụng Moq như trong ví dụ của @ Matt thì bạn có thể xây dựng lớp của riêng bạn mà về cơ bản sẽ giống như vậy.

public class GuidSequenceMocker 
{ 
    private readonly IList<Guid> _guidSequence = new[] 
                { 
                 new Guid("{CF0A8C1C-F2D0-41A1-A12C-53D9BE513A1C}"), 
                 new Guid("{75CC87A6-EF71-491C-BECE-CA3C5FE1DB94}"), 
                 new Guid("{E471131F-60C0-46F6-A980-11A37BE97473}"), 
                 new Guid("{48D9AEA3-FDF6-46EE-A0D7-DFCC64D7FCEC}"), 
                 new Guid("{219BEE77-DD22-4116-B862-9A905C400FEB}") 
                }; 
    private int _counter = -1; 

    public Guid Next() 
    { 
     _counter++; 

     // add in logic here to avoid IndexOutOfRangeException 
     return _guidSequence[_counter]; 
    } 
}