测试 ASP.NET 核心控制器时如何使用 FakeItEasy 动态伪造接口方法

How to fake an Interface method dynamically with FakeItEasy when testing ASP.NET Core controllers

为遵循此模式的 CRUD 控制器编写测试。

  1. 从action方法参数中获取一个或多个不同类型的参数
  2. 调用一些IEntityService.GetEntity(来自步骤 1 的参数)方法
  3. 如果它 return 为 null return NotFound
  4. 否则return找到的对象

我发现自己反复编写非常相似的测试。

        [TestCase(true)]
        [TestCase(false)]
        public void GetsAccount(bool isExistingAccount)
        {
            const int accountId = -1;
            var account = isExistingAccount ? new Account() : null;
            A.CallTo(() => AccountService.GetAccount(accountId)).Returns(account);

            var result = (IStatusCodeActionResult)_controller.GetAccount(accountId);

            var statusCode = isExistingAccount ? HttpStatusCode.OK : HttpStatusCode.NotFound;
            result.StatusCode.Should().Be((int)statusCode);

我试图编写一个通用方法来伪造。

        public void GetEntityActionMethodTest<TEntityType>(bool isExisting, Func<int, TEntityType> serviceMethod, Func<int, ActionResult> actionMethod) where TEntityType : class
        {
            var fakeMethod = A.Fake<Func<int, TEntityType>>();
            A.CallTo(() => fakeMethod(-1)).Returns( isExisting ? default(TEntityType) : null);
            var result = (IStatusCodeActionResult)actionMethod(-1);
            result.StatusCode.Should().Be(isExisting ? (int)HttpStatusCode.OK : (int)HttpStatusCode.NotFound);
        }

它有两个问题:

1) 没有正确伪装成 return null

2) 假设接口方法有一个整型参数

问题

1) 创建一个通用方法是否是个好主意,该方法可以使用 FakeItEasy 伪造在不同接口中可能具有不同签名的方法?用反射怎么样?

2) 如果是,我该怎么做?

谢谢。

我不完全确定你的目标是什么。你说你正在尝试编写一个通用方法来伪造,但你的样本看起来像是完整的测试。我会谈谈如何制作假货。将其合并到测试中应该很简单。

如果目标是创建一个假对象,在调用任何方法时将 return 一个特定对象,由假类型和 return 值参数化,您可以使用 FakeItEasy.Sdk namespace methods to create the object and you can configure the fake to respond to any method 像这样:

public object CreateFakeWithReturnValue(Type typeOfFake, object returnValue)
{
    var fake = Create.Fake(typeOfFake);
    A.CallTo(fake).WithNonVoidReturnType().Returns(returnValue);
    return fake;
}

当然,可以通过查看传入的调用来使此方法更复杂(或者如果您知道伪造的类型,则可以使此方法成为通用方法并仅使用标准 A.Fake建设)。

正如@tom redfern 所说,这可能不是所有情况下的最佳路径,但您必须判断整体方法是否对您有意义。随着测试变得越来越复杂,您可能会发现自己对方法进行了大量扩充,以至于回到 hand-crafted 假货更有意义。