2016-06-15 3 views
2

У меня есть единичный тест, который должен вернуть указанный объект, но он возвращает null.NSubstitute Async возвращает null, несмотря на определенный объект возврата

Поставщик данных для теста:

public class PlanDataProvider : BaseDomainServiceProvider, IPlanDataProvider 
{ 
    //CTOR 
    public PlanDataProvider(IDataAccessTemplate template, IEntityStore entityStore) : base(template, entityStore) 
    { 
    } 

    public async Task<DefaultActionPlan> GetDefaultActionPlan(string referenceListId) 
    { 
     var objectId = GetObjectId(referenceListId); 

     var defaultActionPlan = await Template.InvokeAsync(context => Task.FromResult(EntityStore.GetEntityById<DefaultActionPlan, ObjectId> 
      (
       context.ActivityContext as IDataAccessContext, 
       typeof(DefaultActionPlan).FullName, 
       objectId 
      ))); 
    } 
} 

Тест:

public async Task GetPlan_BadPlanID() 
{ 
    //Arrange 
    string badPlanId = "57509afbc6b48d3f33b2dfcd"; 

    ...snip... 

    DefaultActionPlan jj = new ObjectId(badPlanId); 

    //create EntityStore object 
    var dataxs = Substitute.For<IDataAccessContext>(); 
    var estore = Substitute.For<IEntityStore>(); 
    estore.GetEntityById<DefaultActionPlan, ObjectId>(
     dataxs, 
     typeof(DefaultActionPlan).FullName, 
     new ObjectId(badPlanId)) 
    .Returns(Task.FromResult(jj).Result); 

    var dataAccessTemplate = Substitute.For<IDataAccessTemplate>(); 

    PlanDataProvider pdp = new PlanDataProvider(dataAccessTemplate, estore); 

    //Act 
    var t = await pdp.GetDefaultActionPlan(badPlanId); 
    //Now this confuses me as the compiler thinks t is DefaultActionPlan NOT Task<DefaultActionPlan>??? 
} 

Во всяком случае т возвращает нулевое eferytime и отладки тест т равна нулю, так как в GetDefaultActionPlan не возвращающей JJ, но вместо того, чтобы нуль? ?

Что мне не хватает, чтобы вернуть jj?


Edit:

Оба Eris и Гейб справедливо указал, что мой Мок из IEntityStore не было достаточно, как это значение ... даже если он указывает возврат не будут переданы в упаковке InvokeAsync таким образом, Мне также нужно было выманить InvokeAsync.

Ответ Gabe был немного отпущен, проходя мимо Arg.Any не удовлетворяет требуемым пакетам InvokeAsync. Однако я не виню его за это, так как я провел часы, отслеживая цепочку наследования по нескольким проектам (это большая компания). Что-то у него нет доступа.

В конце концов здесь код, который привел к успеху:

var estore = Substitute.For<IEntityStore>(); 
var dataAccessTemplate = Substitute.For<IDataAccessTemplate>(); 
dataAccessTemplate.InvokeAsync(context => Task.FromResult(
     estore.GetEntityById<DefaultActionPlan>(
       dataxs, typeof(DefaultActionPlan).FullName, new ObjectId(badPlanId)))) 
.ReturnsForAnyArgs(jj); 

var pdp = new PlanDataProvider(dataAccessTemplate, estore); 
+0

При создании заменителя 'IDataAccessTemplate' вы никогда не определяли ни один из его методов. Является ли 'await Template.InvokeAsync' вызовом пустого макета' InvokeAsync' или фактически вызывает метод с аргументами? – Eris

ответ

3

Пока я не вижу это в коде, я буду считать, что GetDefaultActionPlan возвращает переменную defaultActionPlan, и что Template.InvokeAsync является ссылаясь на IDataAccessTemplate, переданный через конструктор.

Похоже, вам не хватает макет возвращаемого значения для Template.InvokeAsync, и так как он оборачивает другие называют ее возвращаемое значение только один вы заботитесь о:

var estore = Substitute.For<IEntityStore>(); 
var dataAccessTemplate = Substitute.For<IDataAccessTemplate>(); 
dataAccessTemplate.InvokeAsync(context => Task.FromResult(Arg.Any<DefaultActionPlan>) 
    .ReturnsForAnyArgs(jj); 

var pdp = new PlanDataProvider(dataAccessTemplate, estore); 
+0

Я верю, что у вас есть я на правильном пути, но все еще пытаюсь выработать несколько нюансов для Mocking оболочки InvokeAsync ... кажется, это не нравится contex => Task.FromResult .... Кажется, мне нужно пройти немного Больше. – GPGVM

+0

Получил! См. Мое редактирование. Спасибо! – GPGVM

+0

Отлично! Я потратил некоторое время на создание простой версии вашего кода, чтобы увидеть, как построить вызов invokeAsync mock, и Arg.Any работал в моем тесте. Просто я понимаю, что estore.GetEntityById возвращает что-то другое, кроме объекта DefaultActionPlan? –

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