c# - What should a controller integration test assert -
doing integration test on web api endpoint should put focus on assert?
my endpoint doing call domain service.
should mock service? current code not possible, because need instantiate controller pass mock service.
am interested in service return value? not. interested wether endpoint succesfully triggered should isolate service call guess.
any advice welcome :-)
test
[testclass] public class schoolyearcontrollertests { private testserver _server; [testinitialize] public void fixtureinit() { _server = testserver.create<startup>(); } [testcleanup] public void fixturedispose() { _server.dispose(); } [testmethod] public void get() { var response = _server.httpclient.getasync(_server.baseaddress + "/api/schoolyears").result; var result = response.content.readasasync<ienumerable<schoolyeardto>>().getawaiter().getresult(); assert.areequal(response.statuscode, httpstatuscode.ok); } }
action test
[httpget] public async task<ihttpactionresult> get() { var schoolyears = await service.getschoolyears(); return ok(schoolyears); }
the trouble doing integration test on web service doesn't tell problem - or if there one, , if there is, doesn't tell issue lies. either succeed or fail. in respect did 200 response code or 500 response code... did fail because:
- the server unreachable
- the web service isn't started, or failed when trying start
- a firewall blocking network
- a database record wasn't found
- there's database schema problem , entity framework didn't start properly.
it literally - , result might different on dev machine in production - tell application?
what makes robust software test product able handle of these situations correctly, gracefully , robustly.
i write controller actions this:
public httpresponsemessage get(int id) { try { var person = _personrepository.getbyid(id); var dto = mapper.map<persondto>(person); httpresponsemessage response = request.createresponse<persondto>(httpstatuscode.ok, dto); return response; } catch (textfiledatasourceexception ex) { httpresponsemessage response = request.createresponse(httpstatuscode.internalservererror); return response; } catch (dataresourcenotfoundexception ex) { httpresponsemessage response = request.createerrorresponse(httpstatuscode.notfound, ex); return response; } catch (formatexception ex) { httpresponsemessage response = request.createerrorresponse(httpstatuscode.internalservererror, ex); return response; } catch (exception ex) { httpresponsemessage response = request.createerrorresponse(httpstatuscode.internalservererror, ex); return response; } }
a try block gets data, makes dto , returns data 200 code. there several error conditions handled here, none indicate problem web service , (404 error) don't indicate issue application - expect notfoundexception , 404 if application can't find record - if happens application works in scenario.
so if of these error conditions occur, not because there's problem web service, , not problem app. can test web service returning correct response of these expected conditions.
the tests controller action looks this:
[test] public void cangetperson() { #region arrange var person = new person { id = 1, familyname = "rooney", givenname = "wayne", middlenames = "mark", dateofbirth = new datetime(1985, 10, 24), dateofdeath = null, placeofbirth = "liverpool", height = 1.76m, twitterid = "@waynerooney" }; mapper.createmap<person, persondto>(); var mockpersonrepository = new mock<ipersonrepository>(); mockpersonrepository.setup(x => x.getbyid(1)).returns(person); var controller = new personcontroller(mockpersonrepository.object); controller.request = new httprequestmessage(httpmethod.get, "1"); controller.configuration = new httpconfiguration(new httproutecollection()); #endregion #region act httpresponsemessage result = controller.get(1); #endregion #region assert assert.areequal(httpstatuscode.ok, result.statuscode); #endregion } [test] public void canhandlepersonnotexists() { #region arrange var mockpersonrepository = new mock<ipersonrepository>(); mockpersonrepository.setup(x => x.getbyid(1)).throws<dataresourcenotfoundexception>(); var controller = new personcontroller(mockpersonrepository.object) { request = new httprequestmessage(httpmethod.get, "1"), configuration = new httpconfiguration(new httproutecollection()) }; #endregion #region act httpresponsemessage result = controller.get(1); #endregion #region assert assert.areequal(httpstatuscode.notfound, result.statuscode); #endregion } [test] public void canhandleservererror() { #region arrange var mockpersonrepository = new mock<ipersonrepository>(); mockpersonrepository.setup(x => x.getbyid(1)).throws<exception>(); var controller = new personcontroller(mockpersonrepository.object); controller.request = new httprequestmessage(httpmethod.get, "1"); controller.configuration = new httpconfiguration(new httproutecollection()); #endregion #region act httpresponsemessage result = controller.get(1); #endregion #region assert assert.areequal(httpstatuscode.internalservererror, result.statuscode); #endregion }
note i'm introducing mock respository , having mock repository trigger expected exceptions 404 , server error , ensuring web service handles correctly.
what tells me web service handling expected , exceptional situations should , returning appropriate codes: 200/404/500.
although error states , success states, none of these outcomes indicate problem web service - behaving should, , that's want test.
an 'across network' integration test on web service tells nothing robustness or correctness of application - or if returning correct data or response-code.
don't try re-test webapi... microsoft wrote massive suite of tests - hundreds of test-fixture classes, thousands of test methods:
assume webapi works should , doesn't require test again. focus on testing application code , make sure success , error conditions handled gracefully web service.
if want check web service connected , available on network - open browser , test manually; there's no need automate this; result vary between environments , according external conditions.
test each layer of application same way, mock out layer above , test current layer handles every possible outcome layer above.
your client application service should same thing: mock web service, , pretend gave 404 - , check handles should.
Comments
Post a Comment