Unit-Test-controller mit MOQ . Wie zum Hohn httpcontext
Versuche ich zu testen, mein Konto controller durch den Einsatz Moq
hier ist, was ich getan habe
Controller
private readonly IWebSecurity _webSecurity;
public AccountController(IWebSecurity webSecurity)
{
this._webSecurity = webSecurity;
}
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && _webSecurity.login(model))
{
return RedirectToLocal(returnUrl);
}
//If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
IWebSecurity
public interface IWebSecurity
{
bool login(LoginModel model);
}
public class WebSecurity : IWebSecurity
{
public bool login(LoginModel model)
{
return WebMatrix.WebData.WebSecurity.Login(model.UserName, model.Password, model.RememberMe);
}
}
MyTestClass
[AfterScenario]
public void OnAfterScenario() {
mockRepository.VerifyAll();
}
LoginModel loginModel;
AccountController _controller;
#region Initializing Mock Repository
readonly Mock<IWebSecurity> mockRepository = new Mock<IWebSecurity>(MockBehavior.Loose);
ViewResult viewResult;
#endregion
[Given]
public void Given_Account_controller()
{
_controller = new AccountController(mockRepository.Object);
}
[When]
public void When_login_is_called_with_LoginModel(Table table)
{
loginModel = new LoginModel
{
UserName = table.Rows[0][1],
Password = table.Rows[1][1]
};
mockRepository.Setup(x => x.login(loginModel)).Returns(true);
viewResult = (ViewResult)_controller.Login(loginModel, "/");
}
[Then]
public void Then_it_should_validate_LoginModel()
{
Assert.IsTrue(_controller.ModelState.IsValid);
}
[Then]
public void Then_it_should_return_default_view()
{
Assert.AreEqual(viewResult.ViewName, "Index");
}
Aber mein test ausfällt und seine Angabe der Erwartung, wenn wenn kommen Url.IsLocal
im Redirect to Local
Methode . also ich denke, hier sollten mock meine httpcontextbase und httpcontextrequestbase .
Aber nicht wissen, wie Sie zu verspotten .
Vielen Dank im Voraus
InformationsquelleAutor Ancient | 2013-06-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
In diesem speziellen Problem können Sie einfach überschreiben controller
Url
Eigenschaft mit verspottetUrlHelper
Klasse.Für
HttpContext
Spott, es könnte gut sein, zu injizierenHttpContextBase
zu Ihrer Steuerung und Konfiguration Ihres DI-container zu dienen, die richtige für Sie. Es würde einfache mocking später für Testzwecke. Ich glaube, Autofac hat einige automatische Weise zu konfigurieren container für ASP.NET-verwandten Klassen wieHttpContextBase
.BEARBEITEN
Es scheint, Sie können nicht verspotten
UrlHelper
mit Moq, da @lazyberezovsky schrieb - Sie verspotten nur die interfaces und virtuelle Methoden. Aber es hört nicht auf, Sie schreiben Ihre eigene verspottet Objekt. Das ist wahr, Sie müssen simulierenHttpContext
, wie es durch die erforderlicheUrlHelper
Konstruktor (eigentlich ist es erforderlich, durchRequestContext
Konstruktor, der erforderlich ist, umUrlHelper
Konstruktor)... Darüber hinausIsLocalUrl
nicht alles verwenden, was aus dem Kontext, so dass Sie nicht haben, um jede zusätzliche Konfiguration.Beispiel-code würde wie folgt Aussehen:
Controller:
Tests:
leider MVC-Entwicklung team-controller hängen direkt von
UrlHelper
Klasse. Die hängt direkt vonRequestContext
. Ich wünschte, es waren Schnittstellen, aber das team machte diese seltsame Entscheidung.du hast Recht. Das ist schade, Controller und UrlHelper sind also eng gekoppelt. Ich bearbeitet meine Antwort und einige code für die Präsentation.
Toll, vielen Dank 🙂
InformationsquelleAutor tdragon
Sollten Sie verhöhnen die
HttpContext
. Ich schrieb diese Helfer zu tun diese Art von Dingenund in einer test-Methode, die Sie verwenden, wie es das
Hoffe es hilft
BasePath
kommt 2 - Was ist der Assembley Namen MockHttpSession(); ?Sorry, ich vergaß ein paar Sachen in der demo. Ich integrierte die Antwort. Der BasePath ist eine einfache variable, die ich verwenden, um die Dateien zu speichern. Jetzt sollte alles wieder funktioniert
InformationsquelleAutor Alessandro Colla