正如标题所说,我正在寻找如何正确测试控制器扩展的方向.扩展呈现部分视图,而我在JSONResult中使用它:
public static string RenderPartialViewToString(this Controller controller, string viewName = null, object model = null)
{
if (string.IsNullOrEmpty(viewName))
{
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
}
controller.ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
public JsonResult Foo()
{
var model = _repository.getSomeData();
return Json(new { html = this.RenderPartialViewToString("Index", model) }, JsonRequestBehavior.AllowGet);
}
Run Code Online (Sandbox Code Playgroud)
我正在使用NUnit和MvcContrib测试助手,但是在设置使用此扩展的控制器时,我遇到了NRE.我假设控制器上下文没有正确设置?
最终,测试正在进行ViewEngines.Engines.FindPartialView.以下是失败测试的一部分:
var routeData …Run Code Online (Sandbox Code Playgroud) asp.net-mvc nunit unit-testing mvccontrib-testhelper asp.net-mvc-3
我试图测试Index控制器的动作.该操作使用AutoMapper将域Customer对象映射到视图模型TestCustomerForm.虽然这有效但我担心测试我从Index行动中收到的结果的最佳方法.
控制器的索引操作如下所示:
public ActionResult Index()
{
TestCustomerForm cust = Mapper.Map<Customer,
TestCustomerForm>(_repository.GetCustomerByLogin(CurrentUserLoginName));
return View(cust);
}
Run Code Online (Sandbox Code Playgroud)
它TestMethod看起来像这样:
[TestMethod]
public void IndexShouldReturnCustomerWithMachines()
{
// arrange
var customer = SetupCustomerForRepository(); // gets a boiler plate customer
var testController = CreateTestController();
// act
ViewResult result = testController.Index() as ViewResult;
// assert
Assert.AreEqual(customer.MachineList.Count(),
(result.ViewData.Model as TestCustomerForm).MachineList.Count());
}
Run Code Online (Sandbox Code Playgroud)
在CreateTestController我Rhino.Mocks用来模拟客户存储库并将其设置为从中返回客户的方法中SetupCustomerForRepository.通过这种方式,我知道存储库将在Index操作调用时返回目标客户_repository.GetCustomerByLogin(CurrentUserLoginName).因此,我认为断言相等的数量足以满足IndexShouldReturnCustomerWithMachines.
所有这些都说我担心我应该测试什么.
result.ViewData.Model as …我正在尝试使用MvcContrib.TestHelper ShouldMapTo <TController>()扩展方法对我的路由进行单元测试,但我的测试失败并显示以下错误消息:
failed: Method MvcContrib.TestHelper.RouteTestingExtensions.ShouldMapTo:
type argument 'ReviewController' violates the constraint of type parameter
'TController'.
Run Code Online (Sandbox Code Playgroud)
但是ReviewController确实符合约束条件.它继承自一个名为SmartController的类,它继承自System.Web.Mvc.Controller.因此,我不知道如何解决此错误.
这是我的单元测试:
[Test]
public void Should_map_review_controller_routes_correctly()
{
MvcApplication.RegisterRoutes(RouteTable.Routes);
"~/reviews"
.ShouldMapTo<ReviewController>(c => c.Index());
}
Run Code Online (Sandbox Code Playgroud)
以下是ReviewController类的声明:
public class ReviewController : SmartController<Review, ReviewForm>
{
...
}
Run Code Online (Sandbox Code Playgroud)
并且SmartController类的声明:
public abstract class SmartController<TModel, TForm> : Controller
where TModel : new()
{
...
}
Run Code Online (Sandbox Code Playgroud)
只是为了咧嘴笑,我尝试从继承层次结构中删除SmartController,以便ReviewController直接从Controller继承,但仍然会抛出错误.
有谁知道我做错了什么?
asp.net-mvc unit-testing asp.net-mvc-routing mvccontrib-testhelper
我正在尝试使用MvcContrib Test Helper来测试MVC3中的控制器方法.
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
考试:
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
result.AssertViewRendered().ForView("Index");
}
Run Code Online (Sandbox Code Playgroud)
错误:
测试方法Tests.Web.Controllers.HomeControllerTests.Index抛出异常:MvcContrib.TestHelper.ActionResultAssertionException:预期结果为ViewResult类型.它实际上是ViewResult类型.
有任何想法吗?
我正在尝试在我的单元测试中使用以下代码,
/* Test setup code */
_routes = RouteTable.Routes;
MvcApplication.RegisterRoutes(_routes); //set up the routes as they would be in actual application
/* test code */
Expression<Func<SearchController, ActionResult>> actionFunc;
actionFunc = action => action.Results("x", 3, null);
RouteTestingExtensions.Route(
"~/Search/Results?searchText=x"
).ShouldMapTo<SearchController>(actionFunc);
Run Code Online (Sandbox Code Playgroud)
问题是,这是失败的"预期结果是结果?searchText = x"
有没有人有一个解决方案可以让我测试一个URL(带有查询字符串)解析为正确的控制器,动作和参数?
仅供参考,我在Global.asax.cs中没有明确的路由设置,因为默认路由适用于实际的应用程序 - 它只是在此测试中不起作用.
我使用nuget和通常的install-package mvccontrib安装了mvccontrib,但我注意到那里没有testhelper.是否有其他方式或标志,我必须用它来安装它.
尝试安装包mvccontrib.testhelper不起作用......
很高兴收到任何想法
我有以下单元测试:
[TestMethod]
public void Add_Returns_Edit_View()
{
// Act
ActionResult result = _controller.Add();
// Verify
result.AssertViewRendered().ForView("Edit");
}
Run Code Online (Sandbox Code Playgroud)
这应该是传递,因为Add操作返回Edit视图.但是,此断言失败,并出现以下异常
MvcContrib.TestHelper.ActionResultAssertionException: Expected view name 'Edit', actual was '~/Views/JobSearch/Edit.cshtml'
Run Code Online (Sandbox Code Playgroud)
为什么视图名称将作为完整路径名返回?这可能是由于我对T4MVC的使用,如果是这样,我怎么能通过?
public virtual ActionResult Add()
{
return View(MVC.JobSearch.Views.Edit, new JobSearch());
}
Run Code Online (Sandbox Code Playgroud) c# asp.net-mvc mvccontrib mvccontrib-testhelper asp.net-mvc-3
在尝试实现上一个问题的第二个答案时,我收到了一个错误.
我已经像帖子所示实现了这些方法,前三个方法正常工作.第四个(HomeController_Delete_Action_Handler_Should_Redirect_If_Model_Successfully_Delete)给出了这个错误:在结果的Values集合中找不到名为'controller'的参数.
如果我将代码更改为:
actual
.AssertActionRedirect()
.ToAction("Index");
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我不喜欢那里的"魔术字符串",而更喜欢使用另一张海报使用的lambda方法.
我的控制器方法如下所示:
[HttpPost]
public ActionResult Delete(State model)
{
try
{
if( model == null )
{
return View( model );
}
_stateService.Delete( model );
return RedirectToAction("Index");
}
catch
{
return View( model );
}
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
我正在尝试为一个控制器编写单元测试,该控制器依赖于生活方式为"PerWebRequest"的类型.
Castle抛出以下异常:
System.InvalidOperationException:HttpContext.Current为null.PerWebRequestLifestyle只能在ASP.Net中使用.
我可以以某种方式模拟HttpContext.Current属性来解决这个问题吗?
我试图使用MVCContrib的TestControllerBuilder来初始化这个控制器,但它没有任何效果.
SymptomTopicController controller = new SymptomTopicController();
controller.WorkOrderFulfillment = workOrderFulfillment;
TestControllerBuilder controllerBuilder = new TestControllerBuilder();
controllerBuilder.InitializeController(controller);
Run Code Online (Sandbox Code Playgroud) 我试图在ASP.NET MVC 3中对我的控制器上的编辑操作进行单元测试.
我通过nuget安装了Mvcontrib.MVC3.TestHelper来模拟我的控制器上下文,但我仍然得到一个NullReferenceException
我的代码看起来像这样:
[TestMethod]
public void it_should_redirect_to_index_after_editing_a_something_successfully()
{
var something= new SomeThing
{
ID = Guid.NewGuid(),
CreatedAt = DateTime.Now,
LastModified = DateTime.Now,
Owner = "Me",
Status = "new",
Title = "my Title",
Attachments = new List<Attachment>()
};
var repo = new FakeRepository();
var controller = new SomethingsController(repo);
new TestControllerBuilder().InitializeController(controller);
var result = controller.Edit(something) as RedirectToRouteResult;
result.AssertActionRedirect().ToAction<SomethingsController>(x => x.Index());
}
Run Code Online (Sandbox Code Playgroud)
生产代码看起来像这样......
[HttpPost]
public ActionResult Edit(SomeThing something)
{
if (ModelState.IsValid)
{
var _something = _repository.GetDocumentByID(something.ID);
TryUpdateModel(_something);
_something.LastModified = DateTime.Now;
_repository.SaveChanges(); …Run Code Online (Sandbox Code Playgroud) asp.net-mvc unit-testing mvccontrib-testhelper asp.net-mvc-3
我刚开始在MvcContrib中使用TestHelpers.我想尝试在我的控制器上测试一个动作方法,该方法本身测试IsAjaxRequest()是否为真.
我使用了TestHelper示例中显示的相同代码来设置TestControllerBuilder
_controller = new StarsController();
_builder = new TestControllerBuilder();
_builder.InitializeController(_controller);
Run Code Online (Sandbox Code Playgroud)
所以_controller里面有所有伪造/模拟的HttpContext,这真的很棒.但是我现在要做什么来强制内部伪造的Request对象上的IsAjaxRequest()返回true?
我有一个示例ASP.NET MVC 3 Web应用程序,遵循Jonathan McCracken的Test-Drive Asp.NET MVC(顺便说一句好书),我偶然发现了一个问题.请注意,我使用的是MVCContrib,Rhino和NUnit.
[Test]
public void ShouldSetLoggedInUserToViewBag() {
var todoController = new TodoController();
var builder = new TestControllerBuilder();
builder.InitializeController(todoController);
builder.HttpContext.User = new GenericPrincipal(new GenericIdentity("John Doe"), null);
Assert.That(todoController.Index().AssertViewRendered().ViewData["UserName"], Is.EqualTo("John Doe"));
}
Run Code Online (Sandbox Code Playgroud)
上面的代码总是抛出这个错误:
System.AccessViolationException:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.
控制器操作代码如下:
[HttpGet]
public ActionResult Index() {
ViewData.Model = Todo.ThingsToBeDone;
ViewBag.UserName = HttpContext.User.Identity.Name;
return View();
}
Run Code Online (Sandbox Code Playgroud)
根据我的想法,应用程序似乎崩溃,因为控制器操作中的两个分配.但是,我看不出有多么错误!?
任何人都可以帮我找出解决这个问题的方法.
谢谢.
编辑1
我做了一些实验来看看问题是什么.删除ViewData,Model分配时,问题会超越Expected result to be of type ViewResult. It is actually of type ViewResult..该ViewData分配是如此基本,我不认为是这样,我认为这个问题有什么问题或者犀牛或MVCcontrib结合MVC 3.
我之前为同一控制器操作编写了以下测试:
[Test]
public void ShouldDisplayAListOfTodoItems() …Run Code Online (Sandbox Code Playgroud) 我是MVCContrib Testhelper的新手和犀牛嘲笑.
我需要协助单元测试依赖于User.Identity.Name,Server.MapPath和Form Collection的控制器.
我开始了
var controller = new SubmitController();
var builder = new TestControllerBuilder();
builder.InitializeController(controller);
Run Code Online (Sandbox Code Playgroud)
我找到了这篇文章来设置User.Identity.Name
controller.ControllerContext = TestHelper.MockControllerContext(controller).WithAuthenticatedUser("domain\\username");
Run Code Online (Sandbox Code Playgroud)
此时,在我的控制器中,我现在可以访问User.Identity.然后问题变成了如何设置Form Collection变量.设置
builder.Form.Add("testvar","1");
Run Code Online (Sandbox Code Playgroud)
不再工作了.现在我似乎必须访问通过
controller.HttpContext.Request.Form.Add("testvar","1)
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但在这一点上,我不再使用上面的构建器(TestControllerBuilder).
然后,我不得不模拟服务器,这引起了更多的问题.如何继续使用构建器,但为httpContext,HttpRequest,Server等使用模拟或存根.我有点期望构建器具有为HttpRequest,Server等设置期望值的方法.
谢谢
asp.net-mvc ×9
unit-testing ×5
c# ×4
mvccontrib ×3
nunit ×2
rhino-mocks ×2
asp.net ×1
automapper ×1
c#-4.0 ×1
httpcontext ×1
nuget ×1
rhino ×1
tdd ×1