如何伪造ASP.NET MVC UrlHelper与FakeitEasy



这是我的控制器的代码:

private readonly ILMS_Service lms_client;
private UrlHelper urlHelper;
public PackagesController(ILMS_Service client, UrlHelper _urlHelper)
{
lms_client = client;
urlHelper = _urlHelper;
}
public PackagesController()
{
lms_client = new LMS_ServiceClient();
urlHelper = new UrlHelper(Request.RequestContext);
}
[HttpPost]
public ActionResult EditPackageDetails(
int packageID,
string package_name,
int unit_type,
int product_id,
int unit_count,
string description
)
{
lms_client.EditPackageDetails(
packageID,
package_name,
unit_type,
product_id,
unit_count,
description);

var url = urlHelper.Action("PackagesList", "Packages");
return Json(new
{
statusCode = (int)HttpStatusCode.OK,
redirectURL = url
});
}

urlBuilder.Action("PackagesList", "Packages");在测试运行期间返回null。我试图通过将UrlHelper类分配给控制器来用假返回值来伪造它,但它似乎不起作用。以下是我的测试的当前实现:

private readonly PackagesController _controller_Packages;
private readonly ILMS_Service _lms_service;
private readonly HttpContextBase httpContext;
private readonly HttpResponseBase httpResponse;
private readonly HttpSessionStateBase httpSession;
private readonly UrlHelper urlBuilder;
public Packages_UnitTest()
{
// Mock WCF
_lms_service = A.Fake<ILMS_Service>();
// Fake session
httpContext = A.Fake<HttpContextBase>();
httpResponse = A.Fake<HttpResponseBase>();
httpSession = A.Fake<HttpSessionStateBase>();
urlBuilder = A.Fake<UrlHelper>();

//SUTs
_controller_Packages = new PackagesController(_lms_service, urlHelper);
A.CallTo(() => httpContext.Response).Returns(httpResponse);
A.CallTo(() => httpContext.Session).Returns(httpSession);
}
[TestMethod]
public void should_EditPackageDetails()
{
// Arrange
int packageID = 1;
string package_name = "Test package";
int unit_type = 1;
int product_id = 1;
int unit_count = 10;
string description = "Sample test description";
int expected_statusCode = (int)HttpStatusCode.OK;
string expected_page_destination = "/Packages/PackagesList";
var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), _controller_Packages);
_controller_Packages.ControllerContext = context;
A.CallTo(() => urlBuilder.Action("PackagesList", "Packages"))
.Returns("/Packages/PackagesList");
// Act
_ = A.CallTo(() => _lms_service.EditPackageDetails(
A<int>.Ignored,
A<string>.Ignored,
A<int>.Ignored,
A<int>.Ignored,
A<int>.Ignored,
A<string>.Ignored
));
var _editPackage = _controller_Packages.EditPackageDetails(
packageID,
package_name,
unit_type,
product_id,
unit_count,
description
) as JsonResult;
dynamic result = _editPackage.Data;
// Assert
Assert.AreEqual(expected_statusCode, result.statusCode);
Assert.AreEqual(expected_page_destination, result.redirectURL);
}

使用此测试,它仍然返回null,而不是"/Packages/PackagesList"。如何使用FakeitEasy将"/Packages/PackagesList"返回为值来伪造UrlHelper?如有任何帮助,我们将不胜感激。我有一个ASP。NET MVC 4、MSTest和FakeitEasy模拟框架。谢谢

UrlHelper对我来说很好,但你没有在EditPackageDetails中使用它。您使用的是您构建的新UrlHelper

var urlBuilder = new UrlHelper(Request.RequestContext);

请改用_controller_Packages.Url

还有一个对未来的提示:调试测试通常会很有帮助。检查你使用的那些你认为可能是假的价值观,看看它们是否真的是。

我最终将UrlHelper注入SUT的构造函数,并添加了一个if语句来检查urlBuilder是否已经实例化。一旦调用了.Action(),它就会返回我定义的伪造路径,正如您在测试的A.CallTo()部分中看到的那样。

请注意,下面的SUT和测试只是我的完整代码的摘录,以消除干扰。

SUT

private UrlHelper urlHelper;
public PackagesController(UrlHelper _urlHelper)
{
urlHelper = _urlHelper;
}
[HttpPost]
public ActionResult EditPackageDetails(
int packageID,
string package_name,
int unit_type,
int product_id,
int unit_count,
string description
)
{
lms_client.EditPackageDetails(
packageID,
package_name,
unit_type,
product_id,
unit_count,
description);
if(urlHelper == null)
urlHelper = new UrlHelper(Request.RequestContext);
var url = urlHelper.Action("PackagesList", "Packages");
return Json(new
{
statusCode = (int)HttpStatusCode.OK,
redirectURL = url
});
}

测试

private readonly PackagesController _controller_Packages;
private readonly ILMS_Service _lms_service;
private readonly UrlHelper urlHelper;
public Packages_UnitTest()
{
// Mock WCF
_lms_service = A.Fake<ILMS_Service>();
// Fakes
urlHelper = A.Fake<UrlHelper>();
// SUTs
_controller_Packages = new PackagesController(_lms_service, urlHelper);
}
[TestMethod]
public void should_EditPackageDetails()
{
// Arrange
int packageID = 1;
string package_name = "Test package";
int unit_type = 1;
int product_id = 1;
int unit_count = 10;
string description = "Sample test description";
int expected_statusCode = (int)HttpStatusCode.OK;
string expected_page_destination = "/Packages/PackagesList";
A.CallTo(() => urlHelper.Action("PackagesList", "Packages"))
.Returns("/Packages/PackagesList");
// Act
_ = A.CallTo(() => _lms_service.EditPackageDetails(
A<int>.Ignored,
A<string>.Ignored,
A<int>.Ignored,
A<int>.Ignored,
A<int>.Ignored,
A<string>.Ignored
));
var _editPackage = _controller_Packages.EditPackageDetails(
packageID,
package_name,
unit_type,
product_id,
unit_count,
description
) as JsonResult;
dynamic result = _editPackage.Data;
// Assert
Assert.AreEqual(expected_statusCode, result.statusCode);
Assert.AreEqual(expected_page_destination, result.redirectURL);
}

我的方法上的if语句似乎是伪造UrlHelper的一种巧妙方法。不过,我无意在那里添加条件语句,所以这不是最优雅的方法。如果有更好的实现,请告诉我。任何附加信息都会有所帮助!

最新更新