好的命名規則,直接從命名就能夠清楚的知道該測試方法測試的內容和目的,而不用額外的添加註釋說明。對於MVC而言,測試Controller是重點。c#
對於Controller的測試,命名方式總共分爲三段:session
Action_Return[_Condition]async
好比以下的Controller:單元測試
public class AdminUserController : Controller { public async Task<IActionResult> Details(string id)
單元測試方法命名以下:測試
[Fact] public async Task Details_ReturnViewResult_WhenExitsUserId() [Fact] public async Task Details_ReturnNotFoundViewResult_WhenNotExitsUserId()
集成測試方法命名以下;ui
[Fact] public async Task Details_ReturnDetailsPage_WhenExitsUserId() [Fact] public async Task Details_ReturnNotFound_WhenNotExitsUserId()
另外,對於需求:Admin帳號登陸以後,菜單額外顯示Admin菜單,單元測試沒法作到,必需要用集成測試:code
[Fact] public async Task Login_ReturnHomePageWithAdminMenu_WhenIsAdmin()
集成測試要比單元測試慢幾個數量級,因此能用單元測試驗證的地方,就不要用集成測試orm
典型的controllers職責:string
避免在controllers中添加沒必要要的職責,以及保證測試僅僅集中在controller的職責,測試controllers的邏輯,在合法和不合法的輸入下的行爲,而不是檢測其餘的方法是否正確,舉個例子:it
[HttpPost] public async Task<IActionResult> Index(NewSessionModel model) { if (!ModelState.IsValid) { return BadRequest(ModelState); } await _sessionRepository.AddAsync(new BrainstormSession() { DateCreated = DateTimeOffset.Now, Name = model.SessionName }); return RedirectToAction("Index"); }
單元測試以下:
[Fact] public async Task IndexPost_ReturnsBadRequest_WhenModelStateIsInvalid() { // Arrange var mockRepo = new Mock<IBrainstormSessionRepository>(); mockRepo.Setup(repo => repo.ListAsync()).Returns(Task.FromResult(GetTestSessions())); var controller = new HomeController(mockRepo.Object); controller.ModelState.AddModelError("SessionName", "Required"); var newSession = new HomeController.NewSessionModel(); // Act var result = await controller.Index(newSession); // Assert var badRequestResult = Assert.IsType<BadRequestObjectResult>(result); Assert.IsType<SerializableError>(badRequestResult.Value); }
注意上面的測試主動給controller的ModelState添加了Error,而不是等Controller的ModelState.IsValid方法來判斷Model是否輸入了SessionName,ModelState.IsValid是否能夠正常工做是集成測試負責的內容,單元測試只要負責檢測 !ModelState.IsValid 時,是否返回BadRequest!單元測試要作的是,覆蓋到Controller的每個Return!
對於通常公用方法的測試,命名方式總共分爲三段:
Action_Return[_Condition]
好比一個用來檢測奇數偶數的類:
public class OddEvenNumberChecker { public bool IsOdd(int number); public bool IsEven(int number); }
單元測試以下:
public class OddEvenNumberCheckerTest { [Fact] public void IsOdd_ReturnTrue_When1357(); [Fact] public void IsOdd_ReturnFalse_When2468(); [Fact] public void IsEven_ReturnFalse_When1357(); [Theory] [InlineData(2)] [InlineData(4)] [InlineData(6)] [InlineData(8)] public void IsEven_ReturnTrue_When2468(int value); }