2014-04-13 55 views
1

下面是一個帶Post方法的控制器。如何在不保存更改到數據庫的情況下針對CREATE方法編寫單元測試?您如何使用EF SaveChanges對MVC控制器進行單元測試

我想寫反對我的控制器檢測,這樣,當其他開發商更改也不會破壞我的功能的代碼(我有功能上的創建方法,一點點地保持簡單現在)。

public class AdministratorController : Controller 
{ 
    private IUnitOfWork _uow; 

[HttpPost] 
public ActionResult Create(MyModel model) 
{ 
    ViewBag.id = model.Id; 

    if (model.FirstName == model.LastName) 
    { 
     ModelState.AddModelError("", "Cannot have same first name and last name."); 
    } 


    if (ModelState.IsValid) 
    { 
     MyClass record = new MyClass(); 

     record.SAFirstName = model.FirstName; 
     record.SALastName = model.LastName; 
     record.SATitle = model.Title; 
     record.SAEmail = model.EmailAddress; 

     record.Since = DateTime.Now; 

     _uow.AdministratorRepository.AddRecord(record); 
     _uow.SaveChanges(); 
     return RedirectToAction("Index", "Administrator"); 
    } 

    return View(model); 
} 

}

2)我UOW看起來是這樣的:

公共類的UnitOfWork:IUnitOfWork { 私人只讀MasterContext _context;

public UnitOfWork(MasterContext context) 
{ 
    _context = context; 
} 

public UnitOfWork() 
{ 
    _context = new MasterContext(); 
} 

public void SaveChanges() 
{ 
    _context.SaveChanges(); 
} 

private IAdministratorRepository _Repo; 

public IAdministratorRepository AdministratorRepository 
{ 
    get 
    { 
     if (this._Repo == null) 
     { 
      this._Repo = new IAdministratorRepository(_context); 
     } 
     return _Repo; 
    } 

}

3)和我AdministratorRepository構造的樣子:

private readonly MasterContext _context; 

    public AdministratorRepository(MasterContext context) 
    { 
     _context = context; 
    } 
+0

經典答案是,你沒有。你抽象出像數據庫這樣的東西。但是,我的新想法是,您使用SQL CE或SQL Server LocalDB來創建一個被抽取到測試生命週期的數據庫。 – Aron

+0

您已經完成了艱苦的工作,通過在可嘲弄的界面後面抽象數據庫訪問。只需創建一個模擬你想要的動作的存根,或者使用一個模擬框架。如果您有任何直接傳遞Linq的方法,那麼您將遇到一些問題,因爲Linq to Entities與Linq對象的行爲略有不同,這是大多數模擬框架將使用的。 –

回答

2

你需要能夠注入假/模擬IUnitOfWork到控制器中。最簡單的方法是在控制器上創建一個內部構造函數,該構造函數接受假對象並創建一個屬性,該屬性可以創建新實例或返回現有實例。

private IUnitOfWork _uow; 
private IUnitOfWork UnitOfWork 
{ 
    get 
    { 
     _uow = _uow ?? new UnitOfWork(); 
     return _uow; 
    } 
} 

public AdministratorController() {} 

internal AdministratorController(IUnitOfWork uow) 
{ 
    _uow = uow; 
} 

您還需要修改MVC項目的AssemblyInfo文件,以使內部構造函數對單元測試項目可見。查找InternalsVisibleToAttribute。

現在在單元測試中,您可以創建假/模擬對象並注入它。你沒有說明你正在使用什麼樣的模擬框架。我們使用FakeItEasy,所以這將是這樣的:

var uow = A.Fake<IUnitOfWork>(); 

var controller = new AdministratorController(uow); 

A.CallTo(() => uow.SaveChanges()).MustHaveHappened(); 
+0

我正在使用MOCK。 – DavidJS

+0

然後你必須調整上面的代碼來使用MOCK來創建你的模擬/假/存根IUnitOfWork。就我個人而言,我從來沒有聽說過MOCK,所以在具體細節方面我不會有太多的幫助,但老實說,在這一點上,你應該能夠從這裏拿走它並且弄清楚你自己創建一個模擬對象的細節。 –

0

你應該在這之後,你應該測試你的期望模型的迴歸模型字段嘲笑你repository.And您dependencies.In你的榜樣的AddRecord()(即你必須設置你的單元測試方法)。