GPG*_*GVM 5 c# unit-testing asynchronous
我有一个单元测试应该返回指定的对象,但它返回 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
)));
}
}
Run Code Online (Sandbox Code Playgroud)
考试:
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>???
}
Run Code Online (Sandbox Code Playgroud)
无论如何 t 返回 null eferytime 并调试测试 t 为 null,因为 GetDefaultActionPlan 不返回 jj 而是返回 null?
我错过了什么才能让 jj 回来?
编辑:
Eris 和 Gabe 都正确地指出,我对 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);
Run Code Online (Sandbox Code Playgroud)
小智 5
虽然我在您的代码中没有看到这一点,但我假设 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);
Run Code Online (Sandbox Code Playgroud)