2012-07-21 3 views
5

Предположим, у меня есть следующий объект: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; } 
} 

И следующий метод интерфейса:

void CreateUser(string username); 

Часть реализации должны создать два новых GUIDs: один для UserGuid, и другой для ConfirmationGuid. Они должны сделать это, установив значения в Guid.NewGuid().

Я уже отведенной Guid.NewGuid() с помощью интерфейса:

public interface IGuidService 
{ 
    Guid NewGuid(); 
} 

Так что я могу легко высмеивать это, когда только один новый GUID необходим. Но я не уверен, как издеваться над двумя разными вызовами одного и того же метода из одного метода, чтобы они возвращали разные значения.

ответ

9

Если вы используете Moq, вы можете использовать:

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

Я полагаю, вы могли бы сделать следующее:

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

Тем не менее, если вы не просто поставлять случайное значение в пределах возврата функции, знание порядка все еще кажется важным.

+0

Но разве это не предполагало, что я устанавливаю свойства в реализации в определенной последовательности? Разве это не замутнение проблемы моего теста? Другими словами, эти поля могут быть установлены в любом порядке, и если по какой-то причине я изменю этот порядок без обновления моих тестов, мои тесты в идеале должны пройти. –

+0

Ну ... вы немного входите в состояние против поведенческого тестирования. Я не знаю, как еще ответить на этот вопрос, не сделав предположения о том, как заказать порядок звонков. –

+3

Если я правильно понимаю, вы не хотите иметь 'Assert.AreEqual (guid1, user.UserGuid); Assert.AreEqual (guid2, user.ConfirmationGuid); 'fail, если вы измените порядок назначения. Вместо этого вы должны использовать некоторый тип утверждения коллекции, который не зависит от порядка (доступен как в nunit, так и в mstest): 'CollectionAssert.AreEquivalent (new [] {guid1, guid2}, new [] {user.UserGuid, user.ConfirmationGuid}) ; ' –

4

Если вы не можете использовать Moq, как в примере @ Matt, тогда вы можете создать свой собственный класс, который будет делать практически то же самое.

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]; 
    } 
}