【问题标题】:Do MVC controllers need parameterized constructors for mocking?MVC 控制器是否需要参数化构造函数来模拟?
【发布时间】:2014-01-23 20:55:24
【问题描述】:

如果我有一个 controller 这样做:

//MyController

public ActionResult MyMethod(string someString)
{
  object test = new object();
  (new MyClassA()).DoSomething(test);
  return View();
}

我是否需要为此控制器创建一个constructor,以便我可以将MyClassA 的模拟版本传递给它?

//Test

Mock<IMyClassA> a = new Mock<IMyClassA>();
a.Setup(m => m.DoSomething(new object());
MyController controller = new MyController(a.Object);

【问题讨论】:

  • 是的,除非你的控制器有默认构造函数。
  • 所以我需要创建一个额外的构造函数只是为了测试?这是不好的做法吗?
  • 有人会说你应该用第二种方式(使用构造函数的依赖注入的 IoC)不管你是否编写控制器测试,但如果你是的话,肯定是这样。
  • 看起来您正在使用 Moq 进行模拟。您可以考虑使用不同的模拟库,例如 FakeItEasy (github.com/FakeItEasy/FakeItEasy),它支持轻松发送模拟参数。

标签: .net asp.net-mvc c#-4.0 mocking tdd


【解决方案1】:

是的,因此,通过其构造函数传递对您希望在某个控制器中使用的所有服务(类)的引用并将其分配给该控制器的私有字段通常是一个好习惯。然后,当调用某个动作时,您不必在此动作的主体内实例化某个类。它还使您能够更轻松地测试/模拟它。

更进一步,您可以考虑使用控制反转(依赖注入)模式,并在控制器的构造函数中传递这些类的接口,而不是传递实际的实现。

所以你的控制器可能看起来像这样:

public class SomeController : Controller
{
    private readonly ISomeService _someService;

    public SomeController(ISomeService someService)
    {
        _someService = someService; 
    }

    public ActionResult Index()
    {
        return View(_someService.GetSomeModel());
    }
}

【讨论】:

    猜你喜欢
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多