Question

De sorte que le contrôleur de contexte dépend de certains asp.net des éléments internes.Ce sont quelques façons à proprement se moquer de ces pour les tests unitaires?On dirait que son très facile de se boucher les tests avec des tonnes de configuration lorsque j'ai seulement besoin de, par exemple, Demande.HttpMethod de retour de "GET".

J'ai vu quelques exemples/aides sur les filets, mais certains sont datés.Pensé que ce serait un bon endroit pour garder les plus récents et les plus grands.

Je suis l'aide de la dernière version de rhino se moque de

Était-ce utile?

La solution

À l'aide de MoQ il ressemble à quelque chose comme ceci:

var request = new Mock<HttpRequestBase>();
request.Expect(r => r.HttpMethod).Returns("GET");
var mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Expect(c => c.Request).Returns(request.Object);
var controllerContext = new ControllerContext(mockHttpContext.Object
, new RouteData(), new Mock<ControllerBase>().Object);

Je pense que le Rhino se moque de la syntaxe est similaire.

Autres conseils

Voici un exemple de test de l'unité de la classe à l'aide de MsTest et Moq se moque de qui HttpRequest et HttpResponse objets.(.NET 4.0, ASP.NET MVC 3.0 )

Action de contrôleur d'obtenir la valeur de la demande et définit l'en-tête http de la réponse des objets.Autres http contexte des objets de la maquette, de la même façon

[TestClass]
public class MyControllerTest
{
    protected Mock<HttpContextBase> HttpContextBaseMock;
    protected Mock<HttpRequestBase> HttpRequestMock;
    protected Mock<HttpResponseBase> HttpResponseMock;

    [TestInitialize]
    public void TestInitialize()
    {
        HttpContextBaseMock = new Mock<HttpContextBase>();
        HttpRequestMock = new Mock<HttpRequestBase>();
        HttpResponseMock = new Mock<HttpResponseBase>();
        HttpContextBaseMock.SetupGet(x => x.Request).Returns(HttpRequestMock.Object);
        HttpContextBaseMock.SetupGet(x => x.Response).Returns(HttpResponseMock.Object);
    }

    protected MyController SetupController()
    {
        var routes = new RouteCollection();
        var controller = new MyController();
        controller.ControllerContext = new ControllerContext(HttpContextBaseMock.Object, new RouteData(), controller);
        controller.Url = new UrlHelper(new RequestContext(HttpContextBaseMock.Object, new RouteData()), routes);
        return controller;
    }

    [TestMethod]
    public void IndexTest()
    {
        HttpRequestMock.Setup(x => x["x"]).Returns("1");
        HttpResponseMock.Setup(x => x.AddHeader("name", "value"));

        var controller = SetupController();
        var result = controller.Index();
        Assert.AreEqual("1", result.Content);

        HttpRequestMock.VerifyAll();
        HttpResponseMock.VerifyAll();
    }
}

public class MyController : Controller
{
    public ContentResult Index()
    {
        var x = Request["x"];
        Response.AddHeader("name", "value");
        return Content(x);
    }
}

Voici un extrait de Jason lien.C'est la même que Phil méthode, mais utilise rhino.

Note:mockHttpContext.La demande est écrasé à retourner mockRequest avant mockRequest internals sont écrasé.Je crois que cette commande est nécessaire.

// create a fake web context
var mockHttpContext = MockRepository.GenerateMock<HttpContextBase>();
var mockRequest = MockRepository.GenerateMock<HttpRequestBase>();
mockHttpContext.Stub(x => x.Request).Return(mockRequest);

// tell the mock to return "GET" when HttpMethod is called
mockRequest.Stub(x => x.HttpMethod).Return("GET");            

var controller = new AccountController();

// assign the fake context
var context = new ControllerContext(mockHttpContext, 
                  new RouteData(), 
                  controller);
controller.ControllerContext = context;

// act
...

La procédure semble avoir été légèrement modifié dans MVC2 (je suis en utilisant RC1).Phil Haack la solution ne fonctionne pas pour moi, si une action nécessite une méthode spécifique ([HttpPost], [HttpGet]).La spéléologie autour de Réflecteur, il semble que la méthode de vérification de ces attributs a changé.MVC vérifie maintenant request.Headers, request.Form, et request.QueryString pour un X-HTTP-Method-Override de la valeur.

Si vous ajoutez se moque de ces propriétés, il fonctionne:

var request = new Mock<HttpRequestBase>();
request.Setup(r => r.HttpMethod).Returns("POST");
request.Setup(r => r.Headers).Returns(new NameValueCollection());
request.Setup(r => r.Form).Returns(new NameValueCollection());
request.Setup(r => r.QueryString).Returns(new NameValueCollection());

var mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Expect(c => c.Request).Returns(request.Object);
var controllerContext = new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock<ControllerBase>().Object);

Ou vous pouvez le faire avec Typemock Isolateur avec pas besoin de nous envoyer un faux contrôleur à tous:

Isolate.WhenCalled(()=>HttpContext.Request.HttpMethod).WillReturn("Get");

je l'ai fini avec cette spécification

public abstract class Specification <C> where C: Controller
{
    protected C controller;

    HttpContextBase mockHttpContext;
    HttpRequestBase mockRequest;

    protected Exception ExceptionThrown { get; private set; }

    [SetUp]
    public void Setup()
    {
        mockHttpContext = MockRepository.GenerateMock<HttpContextBase>();
        mockRequest = MockRepository.GenerateMock<HttpRequestBase>();

        mockHttpContext.Stub(x => x.Request).Return(mockRequest);
        mockRequest.Stub(x => x.HttpMethod).Return("GET");


        EstablishContext();
        SetHttpContext();

        try
        {
            When();
        }
        catch (Exception exc)
        {
            ExceptionThrown = exc;
        }
    }

    protected void SetHttpContext()
    {
        var context = new ControllerContext(mockHttpContext, new RouteData(), controller);
        controller.ControllerContext = context;
    }

    protected T Mock<T>() where T: class
    {
        return MockRepository.GenerateMock<T>();
    }

    protected abstract void EstablishContext();
    protected abstract void When();

    [TearDown]
    public virtual void TearDown()
    {
    }
} 

et le jus est ici

[TestFixture]
public class When_invoking_ManageUsersControllers_Update :Specification   <ManageUsersController>
{
    private IUserRepository userRepository;
    FormCollection form;

    ActionResult result;
    User retUser;

    protected override void EstablishContext()
    {
        userRepository = Mock<IUserRepository>();
        controller = new ManageUsersController(userRepository);

        retUser = new User();
        userRepository.Expect(x => x.GetById(5)).Return(retUser);
        userRepository.Expect(x => x.Update(retUser));

        form = new FormCollection();
        form["IdUser"] = 5.ToString();
        form["Name"] = 5.ToString();
        form["Surename"] = 5.ToString();
        form["Login"] = 5.ToString();
        form["Password"] = 5.ToString();
    }

    protected override void When()
    {
        result = controller.Edit(5, form);
    }

    [Test]
    public void is_retrieved_before_update_original_user()
    {
        userRepository.AssertWasCalled(x => x.GetById(5));
        userRepository.AssertWasCalled(x => x.Update(retUser));
    }
}

profitez de

Je trouve que long se moquant de procédure à trop de frottements.

Le meilleur moyen que nous avons trouvé à l'aide de ASP.NET MVC sur un projet réel - est l'abstraction de la HttpContext à un IWebContext interface qui traverse simplement.Ensuite, vous pouvez vous moquer de la IWebContext avec aucune douleur.

Voici un exemple

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top