2014-02-25 55 views
0

所以我对测试很新,我从来没有做过很多,所以我可能缺乏一些基础知识。如何用Moq位置/过程进行单元测试

问题1: 我正在使用ASP MVC4并希望使用Moq与我的单元测试用例。阅读后有很多例子,我看到我有一个接口。这应该去哪里?在控制器文件夹中,测试项目?

问题2 如果我测试我控制器的方法,它有我怎么会起订量是

public ActionResult Index() 
{ 
var model = new myModel(); 
var pList = new List<myModel.pType>(); 
var sList = new List<myModel.sType>(); 
var results = Class1.FetchPData(); // how would I mock this 
var result1 = Class1.FetchSData(); // how would I mock this 

for (int i = 0; i < results.Count(); i++) 
{ 
    ... do stuff 
} 


for (int j = 0; j < result1.Count(); j++) 
{ 
    ..do stuff 
} 

    return View("Index", model); 
} 

请问我要创建另一个方法,其中包含相同的分贝多个呼叫逻辑,但是我必须传入“模拟对象”作为方法的参数,并将其作为我的界面中的可实现方法?或者重新实施我的方法?

回答

2

阅读后有很多的例子,我看到我假设有 有一个接口。这应该去哪里?在控制器 文件夹中,测试项目?

没有规则在哪里保留接口,但通常你保持它们密切使用它们的代码。通常我有单独的程序集中的域类和服务,其中定义了存储库接口。然后,我通过具有存储库接口实现的数据访问程序集来引用此程序集。最后一步 - 我从web应用程序中引用这两个程序集。

如果我测试我控制器的方法,它有多次调用 分贝我怎么会起订量是

记住,良好的单元测试应该是快速的,孤立的,重复的,自我验证并及时(FIRST)。在控制器中进行数据库调用不允许您快速运行测试(与内存代码相比,数据库调用非常缓慢),以独立地测试控制器并使测试始终可重复。此外,您的控制器只是做很多事情(即违反SRP原则) - 它获取用户输入,进行数据库查询并为查看准备模型。

因此,以分离的责任,使你的控制器可测试,你应该 提取数据访问相关的代码到单独的类(通常这样的类被称为)。并创建了一个抽象,将控制器和存储库之间的指定API:

public interface IYourRepository 
{ 
    IEnumerable<pType> FetchPData(); 
    IEnumerable<sType> FetchSData(); 
} 

然后让你的控制器依赖于这种抽象(逆相关性),并注入存储库控制器(可以使用Ninject,统一或其他依赖注入框架) :

IYourRepository _repository; 

public YourController(IYourRepository repository) 
{ 
    _repository = repository; 
} 

public ActionResult Index() 
{ 
    var model = new myModel(); 

    foreach (var p in _repository.FetchPData()) 
     // do stuff 

    foreach (var s in _repository.FetchSData()) 
     // do stuff 


    return View("Index", model); 
} 

,让您可以轻松地嘲笑库,并提供嘲笑对象控制器:

var repositoryMock = new Mock<IYourRepository>(); 
repositoryMock.Setup(r => r.FetchPData()).Returns(pList); 
repositoryMock.Setup(r => r.FetchSData()).Returns(sList); 

var controller = new YourController(repositoryMock.Object); 
var result = controller.Index(); 

// Assertions 
+0

好吧,我明白知道。所以在将来,我应该用一种也可以轻松模拟的方式编写我的方法 –

+0

我应该提到'FetchPData'和'FetchSData'实际上是从另一个类调用的静态方法。 –

+0

@JackThor即使在你编辑问题后,答案也是一样的 - 使它们非静态并向控制器注入另一个类实例 –