2016-02-18 3 views
2

Изучение Moq и нужна помощь при тестировании результата обратного вызова. Структура: У меня есть объект DateManager, который имеет зависимость от объекта DateServer, который делает асинхронные вызовы на сервер.Тестирование обратного вызова с помощью Moq в C#

DateServer.GetValidDate примет строку даты в yyyy-MM-dd и выполнит данный обратный вызов со строкой в ​​том же формате.

Как настроить макет сервера таким образом, чтобы прошел тест ниже? Простая макетная настройка будет заключаться в том, что мой макет DateServer просто вернет любую строку, предоставленную ему (в обратном вызове).

Вот мои настройки. Я думаю, что у меня большая часть этой структуры правильная, но нужна помощь в заполнении ???? в приведенном ниже коде. Если бы мне лучше проверить обратный вызов, тогда я тоже заинтересован в этом.

public interface IDateServer 
{ 
    // with a currencyPair (ie: USDCAD), verifies that the given date is 
    // valid for a potential transaction. 
    // Callback is used to process the returned result, which is a date string. 
    void GetValidDate(string currencyPair, string date, Action<string> callback); 
} 

public interface IDateManager 
{ 
    void GetDate(string currencyPair, string dateCode, Action<string> callback); 
} 

[TestClass] 
public class DateManagerTests 
{ 
    [TestMethod] 
    public void GetDateTest() 
    { 
     ManualResetEvent ar = new ManualResetEvent(false); 

     Mock<IDateServer> server = new Mock<IDateServer>(); 
     DateTime tradeDate = new DateTime(2016, 2, 17); 

     server.Setup(????); 

     IDateManager dm = new DateManager(tradeDate, server); 

     string ret = ""; 
     dm.GetDate("USDCAD", "2016-02-17", (string s) => 
     { 
      ret = s; 
      ar.Set(); 
     }); 

     ar.WaitOne(); 

     Assert.AreEqual<string>(ret, "2016-02-17"); 

    } 

} 

ответ

2

Если вы хотите хотите проверить DateManager, вы хотите, чтобы убедиться, что DateManager называет GetValidDate метод DateServer зависимости с определенным набором параметров. Метод не возвращает ничего, поэтому нет необходимости в настройке.

Поскольку DataServer, вызывающий метод обратного вызова, не является тестируемым классом, не имеет значения, действительно ли вызван обратный вызов. Вам придется протестировать это в отдельном тесте DateServer.

Таким образом, следующий метод испытания должны подтвердить, что DateManager передает правильные параметры в DateServer (справа в этом случае = параметры, которые были переданы в DateManager):

[TestMethod] 
public void GetDateTest() 
{ 
    Mock<IDateServer> server = new Mock<IDateServer>(); 
    Action<string> callback = (string s) => { }; 
    IDateManager dm = new DateManager(server.Object); 
    dm.GetDate("USDCAD", "2016-02-17", callback); 
    server.Verify(x => x.GetValidDate("USDCAD", "2016-02-17", callback)); 
} 
+0

Итак, мы назвали 'dm.GetDate()', а затем 'Verify()' проверяет правильность вызова 'GetValidDate()'. Это имеет смысл, и для этого случая большая часть. Однако, что произойдет, если мой 'DateManager' будет манипулировать возвращенным результатом до последнего обратного вызова? Я все еще хочу проверить строку, возвращаемую в обратном вызове. Как это сделать? – gdbj

+0

@gdbj AFAIK 'DateServer' - это тот, который должен вызывать обратный вызов. Итак, с точки зрения теста для «DateManager» нет необходимости проверять, действительно ли вызван обратный вызов.В отдельном тесте для 'DateServer' вы должны предоставить фиктивный обратный вызов (без макета) для' DateServer', как это было в вашем примере кода. Кроме того, если 'DateManager' в какой-то момент, как ожидается, вызовет обратный вызов, вы предоставите фиктивный обратный вызов и проверите, было ли это вызвано нужным количеством раз. Поскольку вызовы не могут возникнуть из mock 'DateServer', это был' DateManager'. – Markus

+0

Да, теперь я вижу, что ты прав. Любые проверки утверждений не требуются, так как результат надуман самой установкой. Мне пришлось немного поработать над этим. – gdbj

2

этой установке обратного вызова для GetValidDate и даст вам доступ к любым параметрам, переданным методу, когда она вызывается на издевались интерфейсе.

Mock<IDateServer> server = new Mock<IDateServer>(); 

const string testDateString = "2016-02-17"; 
const string testCurrencyPair = "USDCAD"; 

server.Setup(obj => obj.GetValidDate(It.IsAny<string>(), 
            It.IsAny<string>(), 
            It.IsAny<Action<string>>())) 
     .Callback<string, string, Action<string>>((currencyPair, date, callback) => 
     { 
      // The parameters passed into GetValidDate (see below) 
      // will be available in here. 
      Debug.WriteLine(currencyPair); 
      Debug.WriteLine(date); 
     }); 

server.Object.GetValidDate(testCurrencyPair, testDateString, null); 

Из моего понимания метода Callback это будет только уведомить вас о том, что издевались метод был на самом деле называется и с какими параметрами.

+0

Я не уверен, что это для меня ясно. Я хочу утверждать, что testDateString соответствует тому, что возвращается в обратном вызове. – gdbj

+0

В обратном вызове замените вызовы 'Debug'' Assert.AreEqual (testDateString, date) '. – MotoSV

+0

Параметры, указанные в обратном вызове, то есть 'currencyPair',' date' и 'callback', будут содержать любые значения, передаваемые при любом вызове' server.Object.GetValidDate', даже если вызывается из 'DateManager'. – MotoSV

Смежные вопросы