gpt4 book ai didi

c# - 如何在测试方法 Moq 中设置查询字符串的值

转载 作者:太空狗 更新时间:2023-10-29 18:06:41 24 4
gpt4 key购买 nike

我有以下 Controller 操作方法,我正在为此方法编写单元测试

    try
{
if ( Session["token"] == null)
{
//checking whether the user has already given the credentials and got redirected by survey monkey by checking the query string 'code'
if (Request.QueryString["code"] != null)
{
string tempAuthCode = Request.QueryString["code"];
Session["token"] = _surveyMonkeyService.GetSurveyMonkeyToken(ApiKey, ClientSecret, tempAuthCode, RedirectUri, ClientId);
}
else
{
//User coming for the first time directed to authentication page
string redirectUrlToSurveyMonkeyAuthentication = _surveyMonkeyService.GetUrlToSurveyMonkeyAuthentication(RedirectUri, ClientId, ApiKey);
return Redirect(redirectUrlToSurveyMonkeyAuthentication);
}
}
//User is in the same session no need for token again showing surveys without authentication
var model = _surveyService.GetSurveys(User.Identity.Name);
if (model.Count == 0)
return View(CSTView.NoSurveyTracker.ToString());
return View(CSTView.Index.ToString(), model);
}
catch (Exception e)
{
return DisplayErrorView(e);//Even this returns a redirect method
}

这是我为它编写的单元测试之一,

    [Test]
public void GetIndexPage_Returns_View_With_ValidToken()
{
var mockControllerContext = new Mock<ControllerContext>();
var mockSession = new Mock<HttpSessionStateBase>();
mockSession.SetupGet(s => s["SurveyMonkeyAccessToken"]).Returns(SampleToken);
mockSession.SetupGet(c => c["code"]).Returns(SampleTempAuthCode);
mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);
_surveyTrackerController.ControllerContext = mockControllerContext.Object;
_surveyServiceMock.Setup(x => x.GetSurveys(TestData.TestData.SampleUserName)).Returns(SurveyTrackerList);
var result = _surveyTrackerController.GetIndexPage();
Assert.IsInstanceOf(typeof(ActionResult), result);
Assert.AreEqual(((ViewResult)result).ViewName, "expected");
}

当我尝试运行测试时抛出错误:对象引用未设置为对象的实例,并且行号显示为 request.querystring,如何在测试方法中设置 session 变量,以及任何人都可以建议我检查 Controller 操作返回类型的正确方法是什么。

最佳答案

查询字符串

您还需要在 HttpRequestBase 对象中模拟查询字符串。为此,您需要构建对象图

ControllerContext -> HttpContextBase -> HttpRequestBase

由于您已经模拟了 Controller 实例的 ControllerContext,因此您可以使用以下代码添加模拟的查询字符串:

var queryString = new NameValueCollection { { "code", "codeValue" } };
var mockRequest = new Mock<HttpRequestBase>();
mockRequest.Setup(r => r.QueryString).Returns(queryString);
var mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(c => c.Request).Returns(mockRequest.Object);
mockControllerContext.Setup(c => c.HttpContext).Returns(mockHttpContext.Object);

session

对于模拟 session ,使用上面配置的相同的 http 上下文也返回一个模拟 session 对象:

var mockSession = new Mock<HttpSessionStateBase>();
mockHttpContext.Setup(c => c.Session).Returns(mockSession.Object);
//where mockHttpContext has been created in the code for the queryString above and setup to be returned by the controller context

然后您可以像使用 SetupGet 那样设置值,或者您也可以像在

中那样使用 Setup
mockSession.Setup(s => s["token"]).Returns("fooToken")

如果你想验证 session 中是否设置了一个值,你可以在你的断言代码中添加这样的东西:

mockSession.VerifySet(s => s["token"] = "tokenValue", Times.Once);

ActionResult 类型

我通常做的是使用 as operator 将结果转换为所需的类型.如果无法转换,它将返回 null。所以断言可能看起来像这样:

ViewResult result = controller.Index() as ViewResult;

// Assert
Assert.IsNotNull(result);
Assert.AreEqual("fooView", result.ViewName);

旁注

如果您有许多类似的测试,其中代码使用 session 和/或查询字符串,则您需要在每个测试中创建和配置相当多的模拟对象。

您可以将设置方法添加到您的测试类(在每次测试之前运行),并将使用模拟构建对象图的所有代码移到那里。这样,您在每个测试方法上都有一个新的 Controller 实例,每个测试的安排部分只需要设置模拟行为和期望。

例如,如果您的测试类中有此设置代码:

private HomeController _homeController;
private Mock<HttpSessionStateBase> _mockSession;
private Mock<HttpRequestBase> _mockRequest;

[SetUp]
public void Setup()
{
_mockRequest = new Mock<HttpRequestBase>();
_mockSession = new Mock<HttpSessionStateBase>();
var mockHttpContext = new Mock<HttpContextBase>();
var mockControllerContext = new Mock<ControllerContext>();

mockHttpContext.Setup(c => c.Request).Returns(_mockRequest.Object);
mockHttpContext.Setup(c => c.Session).Returns(_mockSession.Object);
mockControllerContext.Setup(c => c.HttpContext).Returns(mockHttpContext.Object);

_homeController = new HomeController();
_homeController.ControllerContext = mockControllerContext.Object;
}

每个测试的代码都将简化为如下所示:

[Test]
public void Index_WhenNoTokenInSession_ReturnsDummyViewAndSetsToken()
{
// Arrange
var queryString = new NameValueCollection { { "code", "dummyCodeValue" } };
_mockSession.Setup(s => s["token"]).Returns(null);
_mockRequest.Setup(r => r.QueryString).Returns(queryString);

// Act
ViewResult result = _homeController.Index() as ViewResult;

// Assert
Assert.IsNotNull(result);
Assert.AreEqual("dummy", result.ViewName);
_mockSession.VerifySet(s => s["token"] = "tokenValue", Times.Once);
}

[Test]
public void Index_WhenTokenInSession_ReturnsDefaultView()
{
// Arrange
_mockSession.Setup(s => s["token"]).Returns("foo");

// Act
ViewResult result = _homeController.Index() as ViewResult;

// Assert
Assert.IsNotNull(result);
Assert.AreEqual(String.Empty, result.ViewName);
}

那些测试正在测试这个虚拟索引方法的地方

public ActionResult Index()
{
if (Session["token"] == null)
{
if (Request.QueryString["code"] != null)
{

Session["token"] = "tokenValue";
return View("dummy");
}
}
return View();
}

关于c# - 如何在测试方法 Moq 中设置查询字符串的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22311805/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com