c# - Mocking a controller to test ViewEngine inside an Area - nullreference and RouteData -
i have area in mvc site. area has typical controller/model/view setup.
as controller have following code:
public class documentcreatorcontroller : controller { // get: templates/documentcreator public actionresult offertemplate(basedocumentviewmodel data) { return this.pdf(nameof(offertemplate), data, "file.pdf"); } } the method this.pdf couple of stuff, interesting comes down viewengine call:
var viewresult = viewengines.engines.findpartialview(controllercontext, partialviewname); here call findpartialview controllercontext , partialviewname. partialviewname comes nameof(offertemplate) controller action offertemplate. think controllercontext challenge.
my challenge:
when want set in unit test (using moq), have following code based on pages such mocking routedata class in system.web.routing mvc applications , mocking asp.net-mvc controller context:
[testmethod] public void offertemplate() { var ctr = setupcontrollerwithcontext(); } private static documentcreatorcontroller setupcontrollerwithcontext() { var routedata = new routedata(); routedata.values.add("controller", "documentcreatorcontroller"); routedata.values.add("action", "offertemplate"); 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 , routedata, new mock<controllerbase>().object); documentcreatorcontroller ctr = new documentcreatorcontroller(); ctr.controllercontext = controllercontext; return ctr; } which gives following error:
eesy.websites.api.tests.controllers.documentcreatorcontrollertest.offertemplate threw exception: system.nullreferenceexception: object reference not set instance of object.
this don't understand.
my folder setup:
debug image on controllercontext on calling findpartialview:
anyone have idea? because setup routedata wrong?
you trying mock , test framework code. abstract functionality out code control can test in isolation if needed.
currently action , extension controller tightly coupled external 3rd party dependencies. if goal test controller action flow in isolation advised abstract out 3rd party pdf generation can mocked easier testability.
public interface idocumentservice { actionresult topdf(controller arg1, string arg2, object arg3, string arg4); } the controller explicitly depend on abstraction via constructor injection.
public class documentcreatorcontroller : controller { private readonly idocumentservice render; documentcreatorcontroller(idocumentservice render) { this.render = render; } // get: templates/documentcreator public actionresult offertemplate(basedocumentviewmodel data) { return render.topdf(this, nameof(offertemplate), data, "file.pdf"); } } so test controller's pdf generation process need mock abstraction.
[testmethod] public void offertemplate() { //arrange var servicemock = new mock<idocumentservice>(); //...setup mock use case var controller = new documentcreatorcontroller(servicemock.object); var data = new basedocumentviewmodel { //... }; //act var actual = controller.offertemplate(data); //assert //...assert behavior } the actual implementation of service encapsulate actual functionality , registered dependency injection container along abstraction.
to test actual generation need integration test topic.


Comments
Post a Comment