Anggaplah ini adalah metode tindakan saya
public IHttpActionResult Get(int id)
{
var status = GetSomething(id);
if (status)
{
return Ok();
}
else
{
return NotFound();
}
}
Tes akan
var httpActionResult = controller.Get(1);
Bagaimana cara memeriksa kode status http saya setelah ini?
Jawaban:
Berikut
Ok()
ini hanyalah helper untuk tipeOkResult
yang menyetel status respons menjadiHttpStatusCode.Ok
... jadi Anda bisa memeriksa apakah contoh hasil tindakan Anda adalahOkResult
... beberapa contoh (ditulis dalamXUnit
):// if your action returns: NotFound() IHttpActionResult actionResult = valuesController.Get(10); Assert.IsType<NotFoundResult>(actionResult); // if your action returns: Ok() actionResult = valuesController.Get(11); Assert.IsType<OkResult>(actionResult); // if your action was returning data in the body like: Ok<string>("data: 12") actionResult = valuesController.Get(12); OkNegotiatedContentResult<string> conNegResult = Assert.IsType<OkNegotiatedContentResult<string>>(actionResult); Assert.Equal("data: 12", conNegResult.Content); // if your action was returning data in the body like: Content<string>(HttpStatusCode.Accepted, "some updated data"); actionResult = valuesController.Get(13); NegotiatedContentResult<string> negResult = Assert.IsType<NegotiatedContentResult<string>>(actionResult); Assert.Equal(HttpStatusCode.Accepted, negResult.StatusCode); Assert.Equal("some updated data", negResult.Content);
sumber
Assert.IsInstanceOfType(httpActionResult, typeof(OkResult));
Created<T>(url,content)
ituCreatedNegotiatedContentResult
Created
bukan contoh yang baik untuk sebuahGet
operasi ... saya mengubah kode status menjadi yang berbeda sekarang ...OkNegotiatedContentResult<T>
ketika Anda mengirimkan objek jenisT
keOk()
return new StatusCodeResult((HttpStatusCode)422, this);
Saatnya membangkitkan pertanyaan mati
Jawaban saat ini semuanya bergantung pada mentransmisikan objek respons ke tipe yang diketahui. Sayangnya, respons tampaknya tidak memiliki hierarki yang bisa digunakan atau jalur konversi implisit agar ini berfungsi tanpa pengetahuan mendalam tentang implementasi pengontrol. Pertimbangkan hal berikut:
public class MixedCodeStandardController : ApiController { public readonly object _data = new Object(); public IHttpActionResult Get() { return Ok(_data); } public IHttpActionResult Get(int id) { return Content(HttpStatusCode.Success, _data); } }
Menguji kelas:
var testController = new MixedCodeStandardController(); var getResult = testController.Get(); var posRes = getResult as OkNegotiatedContentResult<object>; Assert.IsType<OkNegotiatedContentResult<object>>(getResult); Assert.AreEqual(HttpStatusCode.Success, posRes.StatusCode); Assert.AreEqual(testController._data, posRes.Content); var idResult = testController.Get(1); var oddRes = getResult as OkNegotiatedContentResult<object>; // oddRes is null Assert.IsType<OkNegotiatedContentResult<object>>(idResult); // throws failed assertion Assert.AreEqual(HttpStatusCode.Success, oddRes.StatusCode); // throws for null ref Assert.AreEqual(testController._data, oddRes.Content); // throws for null ref
Dari luar kotak hitam, aliran respons pada dasarnya sama. Pengujian harus mengetahui bagaimana pengontrol mengimplementasikan panggilan balik untuk mengujinya dengan cara ini.
Sebagai gantinya, gunakan objek HttpResponseMessage dari IHttpActionResult yang dikembalikan. Ini memastikan pengujian dapat konsisten, bahkan ketika kode pengontrol mungkin tidak:
var testController = new MixedCodeStandardController(); var getResult = testController.Get(); var getResponse = getResult.ExecuteAsync(CancellationToken.None).Result; Assert.IsTrue(getResponse.IsSuccessStatusCode); Assert.AreEqual(HttpStatusCode.Success, getResponse.StatusCode); var idResult = testController.Get(1); var idResponse = idResult.ExecuteAsync(CancellationToken.None).Result; Assert.IsTrue(idResponse.IsSuccessStatusCode); Assert.AreEqual(HttpStatusCode.Success, idResponse.StatusCode);
sumber
new HttpRequestMessage() {Properties = { { HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration() } }}
Ini adalah jawaban yang diterima oleh Kiran Challa, diadaptasi untuk NUnit;
var valuesController = controller; // if your action returns: NotFound() IHttpActionResult actionResult = valuesController.Get(10); var notFoundRes = actionResult as NotFoundResult; Assert.IsNotNull(notFoundRes); // if your action returns: Ok() actionResult = valuesController.Get(11); var posRes = actionResult as OkResult; Assert.IsNotNull(posRes); // if your action was returning data in the body like: Ok<string>("data: 12") actionResult = valuesController.Get(12); var conNegResult = actionResult as OkNegotiatedContentResult<string>; Assert.IsNotNull(conNegResult); Assert.AreEqual("data: 12", conNegResult.Content); // if your action was returning data in the body like: Content<string>(HttpStatusCode.Accepted, "some updated data"); actionResult = valuesController.Get(13); var negResult = actionResult as NegotiatedContentResult<string>; Assert.IsNotNull(negResult); Assert.AreEqual(HttpStatusCode.Accepted, negResult.StatusCode); Assert.AreEqual("some updated data", negResult.Content);
sumber
https://docs.microsoft.com/en-us/aspnet/web-api/overview/testing-and-debugging/unit-testing-controllers-in-web-api#testing-actions-that-return-ihttpactionresult
Assert.IsInstanceOfType (httpActionResult, typeof (OkResult));
sumber
Setelah beberapa jam meneliti dan mencoba, akhirnya saya menemukan cara untuk menguji sepenuhnya metode API Web 2 saya yang mengembalikan
IHttpActionResult
dan menggunakan middleware OWIN dan implementasi default dari ASP.NET Identity.Saya akan menguji
Get()
metode berikut iniApiController
:public class AccountController : ApiController { private ApplicationUserManager _userManager; public ApplicationUserManager UserManager => _userManager ?? HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); [Route("api/account"), HttpGet] public async Task<IHttpActionResult> Get() { var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); if (user == null) { ModelState.AddModelError(ModelStateConstants.Errors, "Account not found! Try logging out and in again."); return BadRequest(ModelState); } var roles = await UserManager.GetRolesAsync(user.Id); var accountModel = new AccountViewModel { FullName = user.FullName, Email = user.Email, Phone = user.PhoneNumber, Organization = user.Organization.Name, Role = string.Join(", ", roles) }; return Ok(accountModel); } protected override void Dispose(bool disposing) { if (disposing) { if (_userManager != null) { _userManager.Dispose(); _userManager = null; } } base.Dispose(disposing); } }
Mulailah dengan kelas dasar yang akan mewarisi semua kelas pengujian:
public class BaseTest { protected static User CurrentUser; protected static IList<string> Roles; public BaseTest() { var email = "[email protected]"; CurrentUser = new User { FullName = "Unit Tester", Email = email, UserName = email, PhoneNumber = "123456", Organization = new Organization { Name = "Test Organization" } }; Roles = new List<string> { "Administrator" }; } protected void InitializeApiController(ApiController apiController) { //Init fake controller Http and Identity data var config = new HttpConfiguration(); var request = new HttpRequestMessage(); var routeData = new HttpRouteData(new HttpRoute("")); apiController.ControllerContext = new HttpControllerContext(config, routeData, request) { Configuration = config }; apiController.User = new GenericPrincipal(new GenericIdentity(""), new[] { "" }); //Initialize Mocks var appUserMgrMock = GetMockedApplicationUserManager(); var appSignInMgr = GetMockedApplicationSignInManager(appUserMgrMock); var appDbContext = GetMockedApplicationDbContext(); //Configure HttpContext.Current.GetOwinContext to return mocks var owin = new OwinContext(); owin.Set(appUserMgrMock.Object); owin.Set(appSignInMgr.Object); owin.Set(appDbContext.Object); HttpContext.Current = new HttpContext(new HttpRequest(null, "http://test.com", null), new HttpResponse(null)); HttpContext.Current.Items["owin.Environment"] = owin.Environment; } private static Mock<ApplicationSignInManager> GetMockedApplicationSignInManager(Mock<ApplicationUserManager> appUserMgrMock) { var authMgr = new Mock<Microsoft.Owin.Security.IAuthenticationManager>(); var appSignInMgr = new Mock<ApplicationSignInManager>(appUserMgrMock.Object, authMgr.Object); return appSignInMgr; } private Mock<ApplicationUserManager> GetMockedApplicationUserManager() { var userStore = new Mock<IUserStore<User>>(); var appUserMgr = new Mock<ApplicationUserManager>(userStore.Object); appUserMgr.Setup(aum => aum.FindByIdAsync(It.IsAny<string>())).ReturnsAsync(CurrentUser); appUserMgr.Setup(aum => aum.GetRolesAsync(It.IsAny<string>())).ReturnsAsync(Roles); return appUserMgr; } private static Mock<ApplicationDbContext> GetMockedApplicationDbContext() { var dbContext = new Mock<ApplicationDbContext>(); dbContext.Setup(dbc => dbc.Users).Returns(MockedUsersDbSet); return dbContext; } private static IDbSet<User> MockedUsersDbSet() { var users = new List<User> { CurrentUser, new User { FullName = "Testguy #1", Email = "[email protected]", UserName = "[email protected]", PhoneNumber = "123456", Organization = new Organization { Name = "Test Organization" } } }.AsQueryable(); var usersMock = new Mock<DbSet<User>>(); usersMock.As<IQueryable<User>>().Setup(m => m.Provider).Returns(users.Provider); usersMock.As<IQueryable<User>>().Setup(m => m.Expression).Returns(users.Expression); usersMock.As<IQueryable<User>>().Setup(m => m.ElementType).Returns(users.ElementType); usersMock.As<IQueryable<User>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator); return usersMock.Object; } }
The
InitializeApiController
metode berisi daging dan kentang.Sekarang kita bisa menulis tes kita untuk
AccountController
:public class AccountControllerTests : BaseTest { private readonly AccountController _accountController; public AccountControllerTests() { _accountController = new AccountController(); InitializeApiController(_accountController); } [Test] public async Task GetShouldReturnOk() { var result = await _accountController.Get(); var response = await result.ExecuteAsync(CancellationToken.None); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); } }
Agar semuanya berfungsi, Anda harus menginstal banyak
Microsoft.OWIN.*
danMicrosoft.AspNet.*
paket, saya akan menempelkannya dipackages.config
sini:<?xml version="1.0" encoding="utf-8"?> <packages> <package id="Castle.Core" version="4.3.1" targetFramework="net472" /> <package id="EntityFramework" version="6.2.0" targetFramework="net472" /> <package id="Microsoft.AspNet.Identity.Core" version="2.2.2" targetFramework="net472" /> <package id="Microsoft.AspNet.Identity.EntityFramework" version="2.2.2" targetFramework="net472" /> <package id="Microsoft.AspNet.Identity.Owin" version="2.2.2" targetFramework="net472" /> <package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net472" /> <package id="Microsoft.AspNet.WebApi.Core" version="5.2.7" targetFramework="net472" /> <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.7" targetFramework="net472" /> <package id="Microsoft.Owin" version="4.0.1" targetFramework="net472" /> <package id="Microsoft.Owin.Host.SystemWeb" version="4.0.1" targetFramework="net472" /> <package id="Microsoft.Owin.Security" version="4.0.1" targetFramework="net472" /> <package id="Microsoft.Owin.Security.Cookies" version="4.0.1" targetFramework="net472" /> <package id="Microsoft.Owin.Security.OAuth" version="4.0.1" targetFramework="net472" /> <package id="Moq" version="4.10.1" targetFramework="net472" /> <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net472" /> <package id="NUnit" version="3.11.0" targetFramework="net472" /> <package id="Owin" version="1.0" targetFramework="net472" /> <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" /> <package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net472" /> </packages>
Tes ini sangat sederhana, tetapi menunjukkan bahwa semuanya berfungsi :-)
Selamat menguji!
sumber
Jika IHttpActionResult berisi objek JSON, misalnya {"token": "A"}, kita dapat menggunakan kode berikut.
var result = usercontroller.GetLogin("user", "password"); Assert.IsInstanceOfType(result, typeof(OkNegotiatedContentResult<Dictionary<string,string>>)); var content = result as OkNegotiatedContentResult<Dictionary<string, string> >; Assert.AreEqual("A", content.Content["token"]);
sumber