I have a unit test that should return the specified object but it is returning null.
The Data Provider to test:
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
)));
}
}
The Test:
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>???
}
Anyway t returns null eferytime and debugging the test t is null because the GetDefaultActionPlan is not returning jj but instead null??
What am I missing to have jj returned?
Edit:
Both Eris and Gabe rightly pointed out that my Mock of the IEntityStore was not sufficient as that value...even though it specifies a return will not get passed to the wrapping InvokeAsync thus I needed to Mock the InvokeAsync as well.
Gabe's answer was slightly off as passing Arg.Any does not satisfy the InvokeAsync needed parms. However I do not fault him for this as I spent an hours tracking the inheritance chain across multiple projects (this is a big company). Something he does not have access to do.
In the end here is the code that resulted in success:
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);
While I don't see this in your code, I will assume that GetDefaultActionPlan returns the defaultActionPlan variable, and that Template.InvokeAsync is referring to the IDataAccessTemplate passed in via the constructor.
It looks like you are missing a mock return value for Template.InvokeAsync, and since it is wrapping the other call its return value is the only one you care about:
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With