【问题标题】:ASP.NET MVC 2 Unit Testing Stange ErrorsASP.NET MVC 2 单元测试阶段错误
【发布时间】:2010-08-17 06:55:46
【问题描述】:

我正在阅读 Professional ASP.NET MVC 2 这本书,并且我正在尝试让第 1 章中的单元测试正常工作;但是,我遇到了一些非常奇怪的错误。

解决方案中有两个项目:NerdDinner 和 NerdDinner.Tests。

在 NerdDinner 项目中我有以下界面:

IDinnerRepository.cs

//...
namespace NerdDinner.Models
{
     interface IDinnerRepository
     {
     //...
     }
}

同样在 NerdDinner 项目中,我有以下类:

//...
using NerdDinner.Models;
//...
namespace NerdDinner.Controllers
{
     public class DinnersController : Controller
     {
     IDinnerRepository dinnerRepository;
     // Default constructor
     public DinnersController() : this(new DinnerRepository()){} // DinnerRepository is another concrete implementation of IDinnerRepository
     //Test constructor
     public DinnersController(IDinnerRepository repository) {
     dinnerRepository = repository;
     }
     }
}

在 NerdDinner.Tests 项目中,我有以下 IDinnerRepository 的具体实现:

//...
using NerdDinner.Models;
//...
namespace NerdDinner.Tests.Fakes
{
     class FakeDinnerRepository : IDinnerRepository
     {
     //...
          public FakeDinnerRepository(List<Dinner> dinners)
          {
          //...
          }
     //...
     }
}

现在进行实际的单元测试(在 NerdDinner.Tests 中)

using NerdDinner.Controllers;
//...
using NerdDinner.Models;
using NerdDinner.Tests.Fakes;
namespace NerdDinner.Tests
{
     [TestClass]
     public class DinnersControllerTest
     {
          List<Dinner> CreateTestDinners()
          {
          //...
          }
          DinnersController CreateDinnersController()
          {
          return new DinnersController(new FakeDinnerRepository(CreateTestDinners()));
          }
     }
}

现在针对实际问题: 在 DinnerControllerClass 类的 CreateDinnersController 方法中,出现以下错误:

DinnersController.DinnersController(NerdDinner.Models.IDinnerRepository 存储库)(+ 1 个重载) 错误: 'NerdDinner.Controllers.DinnersController.DinnersController(NerdDinner.Models.IDinnerRepository)' 的最佳重载方法匹配有一些无效参数。

它让我可以选择在 DinnersController 中创建构造函数存根。它生成以下代码:

private global::NerdDinner.Tests.Fakes.FakeDinnerRepository repository;
//...
public DinnersController(global::NerdDinner.Tests.Fakes.FakeDinnerRepository repository)
{
     // TODO: Complete member initialization
     this.repository = repository;
}

即使在生成该代码之后,我仍然会遇到同样的错误。但是为什么我还需要那个代码呢?据我所知,我做的一切都是正确的。

谁能帮我弄清楚这里发生了什么?

编辑 生成的代码给出以下错误:

命名空间“NerdDinner”中不存在类型或命名空间“Tests”(您是否缺少任何程序集引用?)

【问题讨论】:

    标签: c# asp.net unit-testing asp.net-mvc-2


    【解决方案1】:

    从您所显示的情况来看,IDinnerRepository 界面是公开的,这意味着它在您的单元测试中不可见。我建议您将其公开,因为我怀疑您有两种不同的接口:一种在单元测试中定义,另一种在您的项目中定义,但存在冲突。另外,我建议您避免依赖 Visual Studio 生成所有垃圾反射代码来测试私有和内部成员。

    【讨论】:

    • 我公开了界面,但我仍然遇到同样的错误。更正:错误不再存在。谢谢!
    • @KPthunder:如果该接口以前不公开,您是如何设法在您的测试项目中实现它的?这就是为什么我建议检查“去定义”会带你去哪里......
    • @Jon Skeet:我刚刚输入了代码,它就起作用了。在我输入接口名称后,IDE 正在为我输入方法。我目前没有在这台计算机上安装 resharper,你认为 resharper 会发现这个吗?
    • @KPthunder:我不确定,但您应该注意 IDE 正在为您做什么 - 接口必须以某种方式进入测试项目,并且你应该对此非常警惕。
    • @Jon Skeet:我不认为该界面在测试项目中,因为当我在未公开时按 F12 时,它会将我带到非测试项目中的界面。
    【解决方案2】:

    您遇到的最后一个错误是由于没有从生产代码引用到测试代码 - 但这是适当的。你不想要那个额外的构造函数。

    相反,您需要找出为什么没有使用采用IDinnerRepository 的现有构造函数。你确定你只有一个叫IDinnerRepository的接口吗?如果你去FakeDinnerRepository源,去声明,把光标放在IDinnerRepository然后按F12(去定义)它去正确的地方吗?

    如果您向IDinnerRepository 添加一个新成员(只是为了测试:void Foo(); 可以)是否会导致生产和假实现都无法编译?

    【讨论】:

    • 是的,F12 将我带到了 NerdDinner.Models 中的一个 IDinnerRepository。当我添加 void foo() 时,它迫使我将所有该方法应用于所有具体实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多