{"id":15072,"date":"2022-05-13T14:17:30","date_gmt":"2022-05-13T12:17:30","guid":{"rendered":"https:\/\/www.centigrade.de\/?post_type=blog&#038;p=15072"},"modified":"2022-05-17T08:14:12","modified_gmt":"2022-05-17T06:14:12","slug":"how-to-engage-graphql-net-and-react-together-part-iii-veda-versum-backend-authentication","status":"publish","type":"blog","link":"https:\/\/www.centigrade.de\/en\/blog\/how-to-engage-graphql-net-and-react-together-part-iii-veda-versum-backend-authentication\/","title":{"rendered":"How to engage GraphQL, .Net and React together: Part III. Veda Versum backend authentication."},"content":{"rendered":"<h2>1. Data persistence<\/h2>\r\n<p>As we have defined before, our API has one main entity &#8211; <em>VedaVersumCard<\/em>. Our application is intended to keep the list of knowledge cards and to grant users the ability to create, read and edit these cards. To make it happen we defined one mutation and 3 queries in our API. <strong><em>\u201cCardAction\u201d<\/em><\/strong> mutation should take the card data as an argument and store this data somewhere. Query <strong><em>\u201callCards\u201d<\/em><\/strong> should return the list of all the existing cards. Query \u201c<strong><em>card<\/em><\/strong>\u201d should return one card by card ID, and \u201c<strong><em>allCardsAssignedToUser<\/em><\/strong>\u201d query should take user E-Mail as input and return cards filtered by property \u201c<strong><em>assignedUsers<\/em><\/strong>\u201d which value equals to that input user.<!--more--><\/p>\r\n<div id=\"attachment_15109\" style=\"width: 1216px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-15109\" class=\"size-full wp-image-15109\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild1-3.png\" alt=\"VedaVersum card entity\" width=\"1206\" height=\"716\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild1-3.png 1206w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild1-3-300x178.png 300w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild1-3-768x456.png 768w\" sizes=\"auto, (max-width: 1206px) 100vw, 1206px\" \/><p id=\"caption-attachment-15109\" class=\"wp-caption-text\">VedaVersum card entity<\/p><\/div>\r\n<p>For the moment this mutation and 3 queries are not implemented and don\u2019t do any relevant actions with our entity. Now it is time to choose which database to use for keeping our cards list. We have a lot of options here. We can use relational database like Oracle or MS SQL Server. But these are industrial giants purposed at working under high load and operate hundreds transactions per second. The lightweight <a href=\"https:\/\/www.sqlite.org\/index.html\">SQLite<\/a> is more suitable for small applications. Main advantages of SQLite are as follows:<\/p>\r\n<ul>\r\n<li>it\u2019s free and open-source<\/li>\r\n<li>it keeps the data in a single file and doesn\u2019t need any server to run database engine.<\/li>\r\n<li>dotNet has brilliant tool for working with relational databases called <a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/\">Entity Framework<\/a>.<\/li>\r\n<\/ul>\r\n<p>But from the other hand as every relational database, SQLite requires to define strongly-typed database scheme. For example, in our <em>VedaVersum<\/em> entity we can define some other properties like \u201cArchived\u201d flag in the future. In case of relational database this is a breaking change which requires some efforts to provide scheme migrations with already existing database. They are justified if we have rich good-structured denormalized data model which is not changing too often. But in our case <em>VedaVersum<\/em> entities it\u2019s just a list of documents. NoSQL database is perfect database to store the lists of documents. That\u2019s why we will use <a href=\"https:\/\/www.mongodb.com\/\">MongoDB<\/a>. This is the main player in the world of NoSQL databases. It is free and open-source. It stores data as list of JSON documents and does not require strongly-typed database scheme. And it provides high performance, scaling and backup tools such as all serious databases.<\/p>\r\n<h3>2.1. Setup MongoDB<\/h3>\r\n<p>If you never used Mongo in your development machine, first you should install database engine. <a href=\"https:\/\/docs.mongodb.com\/manual\/installation\/\">Here are some instructions how you can do this<\/a>. I use <a href=\"https:\/\/www.docker.com\/products\/docker-desktop\">Docker desktop<\/a> on my machine and have MongoDB started as docker container.<\/p>\r\n<p>As soon as we have MongoDB engine up and running, we can use it in our project. There is a <a href=\"https:\/\/docs.mongodb.com\/drivers\/csharp\/\">MongoDB driver for dotNet<\/a> which we will use in our project, so first we should add a <a href=\"https:\/\/www.nuget.org\/packages\/mongodb.driver\">Nuget package<\/a> to our project.<\/p>\r\n<p>Secondly, we should add a new parameter to our <em>appsettings.json<\/em> with the <a href=\"https:\/\/mongodb.github.io\/mongo-csharp-driver\/2.14\/reference\/driver\/connecting\/\">connection string<\/a>.<\/p>\r\n<p>And thirdly, we should define a new interface <strong><em>IVedaVersumDataAccess<\/em><\/strong> and <strong><em>VedaVersumDataAccess <\/em><\/strong>service which implements this interface.<\/p>\r\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15112\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild2-3.png\" alt=\"IVedaVersumDataAccess and VedaVersumDataAccess \" width=\"321\" height=\"136\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild2-3.png 321w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild2-3-300x127.png 300w\" sizes=\"auto, (max-width: 321px) 100vw, 321px\" \/><\/p>\r\n<h3>2.2. Data access implementation<\/h3>\r\n<p>We have defined the data access interface with CRUD operations. We will use this interface in our mutation and queries. And here I am briefly describing the implementation of data access itself.<\/p>\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n  &quot;ConnectionStrings&quot;: {\r\n    &quot;mongo&quot;: &quot;mongodb:\/\/localhost:27017&quot;\r\n  }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p><a href=\"https:\/\/github.com\/Centigrade\/vedaversum\/blob\/main\/VedaVersum.Backend\/DataAccess\/VedaVersumDataAccess.cs\">VedaVersumDataAccess.cs<\/a><\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public class VedaVersumDataAccess : IVedaVersumDataAccess\r\n    {\r\n        private const string DatabaseName = &quot;VedaVersum&quot;;\r\n        private const string VedaVersumCardsCollectionName = &quot;Cards&quot;;\r\n        private readonly IMongoDatabase _database;\r\n        public VedaVersumDataAccess(string mongoDbConnectionString, ILogger&lt;VedaVersumDataAccess&gt; logger)\r\n        {\r\n            var mongoConnectionUrl = new MongoUrl(mongoDbConnectionString);\r\n            var mongoClientSettings = MongoClientSettings.FromUrl(mongoConnectionUrl);\r\n            mongoClientSettings.ClusterConfigurator = cb =&gt; {\r\n                cb.Subscribe&lt;CommandStartedEvent&gt;(e =&gt; {\r\n                    logger.LogDebug($&quot;{e.CommandName} - {e.Command.ToJson()}&quot;);\r\n                });\r\n            };\r\n            var client = new MongoClient(mongoClientSettings);\r\n            _database = client.GetDatabase(DatabaseName);\r\n        }\r\n\r\n        \/\/\/ &lt;inheritdoc \/&gt;\r\n        public async Task DeleteCard(string cardId)\r\n        {\r\n            var cardsCollection = _database.GetCollection&lt;VedaVersumCard&gt;(VedaVersumCardsCollectionName);\r\n            await cardsCollection.DeleteOneAsync(Builders&lt;VedaVersumCard&gt;.Filter.Where(c =&gt; c.Id == cardId));\r\n        }\r\n\r\n        \/\/\/ &lt;inheritdoc \/&gt;\r\n        public async Task&lt;IEnumerable&lt;VedaVersumCard&gt;&gt; GetAll()\r\n        {\r\n            var cardsCollection = _database.GetCollection&lt;VedaVersumCard&gt;(VedaVersumCardsCollectionName);\r\n            var allCards = await cardsCollection.FindAsync(Builders&lt;VedaVersumCard&gt;.Filter.Empty);\r\n            return allCards.ToList();\r\n        }\r\n        \/\/ Code omitted for brevity\r\n    }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>startup.cs<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n            \/\/ DataAccess\r\n            var connectionString = Configuration.GetConnectionString(&quot;mongo&quot;);\r\n            services.AddTransient&lt;IVedaVersumDataAccess, VedaVersumDataAccess&gt;((p) =&gt; new VedaVersumDataAccess(\r\n                connectionString, \r\n                p.GetService&lt;ILogger&lt;VedaVersumDataAccess&gt;&gt;()!));\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>You can find full code in <a href=\"https:\/\/github.com\/Centigrade\/vedaversum\/tree\/main\/VedaVersum.Backend\">GitHub<\/a> repository. As you can see, it\u2019s pretty simple to use MongoDB in ASP.Net core application. And here are our API methos working:<\/p>\r\n\r\n\r\n\r\n<p>Create Card:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"538\" height=\"343\" class=\"wp-image-15114\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild3-3.png\" alt=\"Create Card\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild3-3.png 538w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild3-3-300x191.png 300w\" sizes=\"auto, (max-width: 538px) 100vw, 538px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>Read All Cards:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"550\" height=\"351\" class=\"wp-image-15116\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild4-3.png\" alt=\"Read All Cards\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild4-3.png 550w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild4-3-300x191.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>Update card:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"550\" height=\"361\" class=\"wp-image-15118\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild5-2.png\" alt=\"Update card\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild5-2.png 550w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild5-2-300x197.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>We have implemented data persistence in our application! Yay!<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">3. GraphQL resolvers and data loaders<\/h2>\r\n\r\n\r\n\r\n<p>Now it\u2019s time to talk a little bit about data objects cross references and performance. As you have already noticed, every knowledge card has a list of related card Ids. The cards are stored in the database with this structure:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"592\" height=\"377\" class=\"wp-image-15122\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild6-2.png\" alt=\"Stored cards\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild6-2.png 592w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild6-2-300x191.png 300w\" sizes=\"auto, (max-width: 592px) 100vw, 592px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>So, \u201ccard two\u201d references the \u201ccard one\u201d, \u201ccard three\u201d references \u201ccards two and one\u201d and so on. If we are fetching all cards, maybe it\u2019s not a big problem. But what if client app wants to request only \u201ccard three\u201d and all its dependencies, our query will look like this:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"592\" height=\"299\" class=\"wp-image-15124\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild7-2.png\" alt=\"card query\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild7-2.png 592w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild7-2-300x152.png 300w\" sizes=\"auto, (max-width: 592px) 100vw, 592px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>For related cards we have only Ids and to get their content the client should call the same query two more times. And if there are more than two related cards, number of requests from client to server dramatically increases. This situation is usual for REST API and called \u201cn+1 problem\u201d.<\/p>\r\n\r\n\r\n\r\n<p>Fortunately, one of the GraphQL tasks is the ability to eliminate this n+1 problem. We can define some query hook called <strong><em>Resolver<\/em><\/strong>. This resolver allows client to fetch all related objects at one request. Let\u2019s add this <a href=\"https:\/\/github.com\/Centigrade\/vedaversum\/blob\/main\/VedaVersum.Backend\/Api\/VedaVersumCardObjectType.cs\">resolver<\/a> to our GraphQL API for related cards:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public class VedaVersumCardObjectType: ObjectType&lt;VedaVersumCard&gt;\r\n    {\r\n        protected override void Configure(IObjectTypeDescriptor&lt;VedaVersumCard&gt; descriptor)\r\n        {\r\n            descriptor\r\n            .Field(&quot;relatedCards&quot;) \/\/ Name of the additional field\r\n            .Type&lt;ListType&lt;VedaVersumCardObjectType&gt;&gt;()\r\n            .Resolve(async context =&gt;\r\n            {\r\n                var parent = context.Parent&lt;VedaVersumCard&gt;();\r\n\r\n                if(parent.RelatedCardIds == null || parent.RelatedCardIds.Count == 0)\r\n                {\r\n                    return new List&lt;VedaVersumCard&gt;();\r\n                }\r\n\r\n                var dataAccess = context.Service&lt;IVedaVersumDataAccess&gt;();\r\n                return await dataAccess.GetCardsById(parent.RelatedCardIds);\r\n            });\r\n        }\r\n    }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>This object type extends our <strong><em>VedaVersumCard<\/em><\/strong> object adding a new field to it. And implements the logic of filling this field. Now we must add this new object type definition to our GraphQL server setup at <strong>startup.cs<\/strong>.<\/p>\r\n\r\n\r\n\r\n<p>&nbsp;<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"751\" height=\"521\" class=\"wp-image-15126\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild8-2.png\" alt=\"extend VedaVersumCard \" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild8-2.png 751w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild8-2-300x208.png 300w\" sizes=\"auto, (max-width: 751px) 100vw, 751px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>And we can run our query again:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"480\" height=\"298\" class=\"wp-image-15128\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild9-2.png\" alt=\"Run Query\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild9-2.png 480w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild9-2-300x186.png 300w\" sizes=\"auto, (max-width: 480px) 100vw, 480px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>As you could notice, there is an additional field in the query called \u201crelatedCards\u201d, and we can get all related cards information just using single request to GraphQL server. So, we have just got rid of our n+1 problem. Bingo!<\/p>\r\n\r\n\r\n\r\n<p>There is one more point. GraphQL allows both to query related data by single request and to construct the query the way that the same API method can be called multiple times with different parameters but using only one request. For instance, the client application has the IDs of three cards. The client can construct the query to get the details of all 3 cards using this query:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"513\" height=\"318\" class=\"wp-image-15130\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild10-1.png\" alt=\"construct query\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild10-1.png 513w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild10-1-300x186.png 300w\" sizes=\"auto, (max-width: 513px) 100vw, 513px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>It works perfectly. I can get any data I want without the above-mentioned n+1 problem. But if I were curious and attached a logger to the MongoDB client, I could see that GraphQL server made 3 subsequent requests to the database with that single request.<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"698\" height=\"281\" class=\"wp-image-15132\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild11-1.png\" alt=\"database dbug\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild11-1.png 698w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild11-1-300x121.png 300w\" sizes=\"auto, (max-width: 698px) 100vw, 698px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>Let\u2019s take a look again to our query method:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Returns card by ID\r\n        \/\/\/ &lt;\/summary&gt;\r\n        public async Task&lt;VedaVersumCard?&gt; GetCardById(string cardId)\r\n        {\r\n            return _dataAccess.GetCardById(cardId);\r\n        }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>In spite of the single query to GraphQL, the resolver is executed each time for each ID. And each time it uses the data access to fetch one card from DB. So, n+1 problem still exists, but inside of our backend server.<\/p>\r\n\r\n\r\n\r\n<p>Fortunately, GraphQL can handle this problem too. There is another concept called <strong>DataLoader<\/strong>. And here we can <a href=\"https:\/\/github.com\/Centigrade\/vedaversum\/blob\/main\/VedaVersum.Backend\/Api\/VedaVersumCardDataLoader.cs\">implement<\/a> it:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public class VedaVersumCardDataLoader : BatchDataLoader&lt;string, VedaVersumCard&gt;\r\n    {\r\n        private readonly IVedaVersumDataAccess _vedaVersumDataAccess;\r\n\r\n        public VedaVersumCardDataLoader(\r\n            IVedaVersumDataAccess vedaVersumDataAccess,\r\n            IBatchScheduler batchScheduler,\r\n            DataLoaderOptions&lt;string&gt;? options = null) : base(batchScheduler, options)\r\n        {\r\n            _vedaVersumDataAccess = vedaVersumDataAccess;\r\n        }\r\n\r\n        \/\/ This method collects all CardIds during the single GraphQL query and executes database query once far all CardIds\r\n        protected override async Task&lt;IReadOnlyDictionary&lt;string, VedaVersumCard&gt;&gt; LoadBatchAsync(\r\n            IReadOnlyList&lt;string&gt; keys, CancellationToken cancellationToken)\r\n        {\r\n            var allCardsByIds = await _vedaVersumDataAccess.GetCardsById(keys);\r\n            return allCardsByIds.ToDictionary(c =&gt; c.Id);\r\n        }\r\n    }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>So, under the hood the GraphQL query parser can get all CardIds during single GraphQL query and use this <strong>DataLoader<\/strong> to execute batch database query. Let\u2019s apply this data Loader to our query resolver:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Returns card by ID\r\n        \/\/\/ &lt;\/summary&gt;\r\n        public async Task&lt;VedaVersumCard?&gt; GetCard(string cardId, VedaVersumCardDataLoader dataLoader)\r\n        {\r\n            return await dataLoader.LoadAsync(cardId, CancellationToken.None);\r\n        }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Now we can execute this GraphQL query once again:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"513\" height=\"318\" class=\"wp-image-15134\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild12-1.png\" alt=\"Execute GraphQL\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild12-1.png 513w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild12-1-300x186.png 300w\" sizes=\"auto, (max-width: 513px) 100vw, 513px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>And look into the logs:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"642\" height=\"259\" class=\"wp-image-15136\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild13-1.png\" alt=\"Execute GraphQL Logs\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild13-1.png 642w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild13-1-300x121.png 300w\" sizes=\"auto, (max-width: 642px) 100vw, 642px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>There is only one batch query. Cool, we have eliminated the n+1 problem at all levels and client can use our GraphQL API with different query combinations with optimal performance.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">4. Unit testing<\/h2>\r\n\r\n\r\n\r\n<p>At this point backend service has already been put to work. That\u2019s great! And while we were developing everything, we used to start the application and check if authorization works, if persistence works, if queries, mutations, and subscription work. And of course, we had to ensure all services and their dependencies to be properly set up. We were doing all these activities using \u201cStrawberry Shake\u201d IDE for GraphQL queries. When we develop UI, we will check some UI activities, user scenarios and how everything works together with backend running. At the development phase we do it manually and \u201coccasionally\u201d. We don\u2019t cover every scenario and use case. This is called \u201csmoke testing\u201d \u2013 just to check if application starts at least and can pass main scenario without creepy run-time errors. But this testing does not guarantee our application to work properly and to be ready for production use.<\/p>\r\n\r\n\r\n\r\n<p>For large applications it is usually recommended to construct Integration test scenarios covering the whole application functionality. These integration tests are supposed to be created by another person, not the one who developed the application. There is usually a role in the team called Quality Assurance Engineer, who is responsible for test scenarios. Integration tests can be automated or can be run manually for each development phase. Integration testing and Quality Assurance is a big and important part of the development process. But this is another long story.<\/p>\r\n\r\n\r\n\r\n<p>But there is another important part of Development process called Unit testing. This part is the developers\u2019 responsibility and should be closely related to the main application functionality development. There is common practice to follow <a href=\"https:\/\/en.wikipedia.org\/wiki\/Test-driven_development\">Test Driven Development<\/a> process. For example, we have defined <strong><em>IVedaVersumDataAccess<\/em><\/strong> interface in our application with some methods to manipulate the database. We have implemented this interface with class <strong><em>VedaVersumDataAccess<\/em><\/strong>. Also we have injected this interface to Query and Mutation resolvers. And when client calls query or mutation, the appropriate resolver will be involved. And then, this resolver should call appropriate data access method, which should return with some predictable result. We have already described the scenario for unit test. We can write the test methods which create an instance of Mutation class and inject <strong><em>IVedaVersumDataAccess<\/em><\/strong> in this class. But in unit test we don\u2019t have to call real database. We can substitute the data access real implementation class with mock implementation. And we can manipulate this mock implementation in the test method and check if some method has been called with some expected parameters and so on.<\/p>\r\n\r\n\r\n\r\n<p>Therefore, I can \u201cdetach\u201d one part of the program and write test scenario checking this particular intermediate part of our application. And I can write as many scenarios as I need to cover all classes (or units) logic without constructing the whole complicated dependencies between different application modules. For example, we have the <strong><em>VedaVersumMutation<\/em><\/strong> class. And data mutating method has this algorithm:<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"407\" height=\"336\" class=\"wp-image-15138\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild14-1.png\" alt=\"the VedaVersumMutation class\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild14-1.png 407w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Bild14-1-300x248.png 300w\" sizes=\"auto, (max-width: 407px) 100vw, 407px\" \/><\/figure>\r\n\r\n\r\n\r\n<p>And to be sure in this algorithm\u2019s proper work we should write a test scenario for each block in this algorithm. As you can see, method uses Database and Subscription sender service. These two dependencies are injected into the class through the constructor:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public class VedaVersumMutation\r\n    {\r\n        private readonly ITopicEventSender _eventSender;\r\n        private readonly IVedaVersumDataAccess _dataAccess;\r\n\r\n\r\n        public VedaVersumMutation(ITopicEventSender eventSender, IVedaVersumDataAccess dataAccess)\r\n        {\r\n            _eventSender = eventSender;\r\n            _dataAccess = dataAccess;\r\n        }\r\n     \/\/ Code omitted for brevity\r\n    }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>To test <strong><em>CardAction<\/em><\/strong> mutation method, we should create a <strong><em>VedaVersumMutation<\/em><\/strong> class object and call this method. But we can inject <strong><u>mock<\/u><\/strong> <em>DataAccess<\/em> and <em>EventSeder<\/em> objects instead of real objects in the tests which are used when program runs in a \u201cproduction mode\u201d. With these mock objects we can check if appropriate methods were called with appropriate parameters. Therefore, we can test only this particular algorithm and don\u2019t care about database and other dependencies.<\/p>\r\n\r\n\r\n\r\n<p>To do that I have created a test project which uses <a href=\"https:\/\/nunit.org\/\">NUnit<\/a> testing framework and <a href=\"https:\/\/riptutorial.com\/moq\">Moq<\/a> library for setting up mock objects. And this can show you how to test this method:<\/p>\r\n\r\n\r\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public class VedaVersumMutationTests\r\n    {\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Event sender mock object\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private Mock&lt;ITopicEventSender&gt; _eventsSenderMock = new Mock&lt;ITopicEventSender&gt;();\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ DataAccess mock object\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private Mock&lt;IVedaVersumDataAccess&gt; _dataAccessMock = new Mock&lt;IVedaVersumDataAccess&gt;();\r\n        private VedaVersumMutation MutationClassToTest;\r\n\r\n        &#x5B;SetUp]\r\n        public void Setup()\r\n        {\r\n            MutationClassToTest = new VedaVersumMutation(_eventsSenderMock.Object, _dataAccessMock.Object);\r\n        }\r\n\r\n        &#x5B;Test]\r\n        public async Task ShouldCallInsertNewCardDataAccessMethodOnCardCreate()\r\n        {\r\n            \/\/ Arrange. Mocking dataAccess behavior\r\n            _dataAccessMock.Setup(d=&gt; d.InsertNewCard(It.IsAny&lt;string&gt;(), It.IsAny&lt;string&gt;(), null, It.IsAny&lt;User&gt;()))\r\n                .ReturnsAsync(ExpectedCardData);\r\n\r\n            \/\/ Action\r\n            var resultCard = await MutationClassToTest.CardAction(\r\n                VedaVersumCardAction.Create, \r\n                ExpectedCardData.Title,\r\n                ExpectedCardData.Content,\r\n                relatedCards: null,\r\n                cardId: null,\r\n                TestUser);\r\n\r\n            \/\/ Assert\r\n            Assert.NotNull(resultCard);\r\n            Assert.IsNotEmpty(resultCard.Id);\r\n            Assert.AreEqual(ExpectedCardData.Title, resultCard.Title);\r\n            \/\/ Check if data accessor&#039;s InsertNewCard method has been called only once and with appropriate parameters\r\n            _dataAccessMock.Verify(d =&gt; d.InsertNewCard(\r\n                ExpectedCardData.Title, \r\n                ExpectedCardData.Content,\r\n                null,\r\n                It.IsAny&lt;User&gt;()\r\n                ), Times.Once);\r\n            \/\/ Check if EventSender&#039;s method SendAsync has been called only once\r\n            _eventsSenderMock.Verify(s =&gt; s.SendAsync&lt;string, CardActionMessage&gt;(\r\n                nameof(VedaVersumSubscription.CardChanged), \r\n                It.Is&lt;CardActionMessage&gt;(m =&gt; m.Action == VedaVersumCardAction.Create),\r\n                It.IsAny&lt;CancellationToken&gt;()),\r\n                Times.Once);\r\n        }\r\n\r\n        &#x5B;TestCase(VedaVersumCardAction.Update)]\r\n        &#x5B;TestCase(VedaVersumCardAction.Delete)]\r\n        public void ShouldThrowExceptionIfActionIsNotCreateAndCardIdIsNull(VedaVersumCardAction action)\r\n        {\r\n            Assert.ThrowsAsync&lt;ArgumentNullException&gt;(() =&gt; MutationClassToTest.CardAction(\r\n                action, \r\n                ExpectedCardData.Title,\r\n                ExpectedCardData.Content,\r\n                relatedCards: null,\r\n                cardId: null,\r\n                TestUser));\r\n        }\r\n\r\n        \/\/ Other test scenarios are omitted\r\n    }\r\n\r\n<\/pre><\/div>\r\n\r\n\r\n<p>Full test project you can find in the <a href=\"https:\/\/github.com\/Centigrade\/vedaversum\/tree\/main\/VedaVersum.Test\">repository<\/a>. Now we can start these tests using Test Explorer in VS 2022 or using command line \u201cdotnet test\u201d, and ensure that all tests are green.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\r\n\r\n\r\n\r\n<p>We have played with a lot of stuff today. We have implemented the GraphQL API, we have added MongoDB as data persistence to our API. We have looked to some cool features of GraphQL such as Resolvers and Data Loaders. Finally, we have created some unit tests. And have closed the round of typical backend development lifecycle. Hope you enjoyed our journey. In the next part of our series, we will create the UI application with React.<\/p>\r\n\r\n\r\n\r\n<p>See you soon &#8211; Stay tuned!<\/p>\r\n<p>&nbsp;<\/p>\r\n\r\n\r\n","protected":false},"author":66,"featured_media":0,"template":"","tags":[177,886,235,885,653,8,638],"class_list":["post-15072","blog","type-blog","status-publish","hentry","tag-net","tag-api","tag-csharp","tag-graphql","tag-react-en","tag-software-developers","tag-ux-engineering-en-2"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/blog\/15072","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/users\/66"}],"version-history":[{"count":13,"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/blog\/15072\/revisions"}],"predecessor-version":[{"id":15155,"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/blog\/15072\/revisions\/15155"}],"wp:attachment":[{"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/media?parent=15072"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.centigrade.de\/en\/wp-json\/wp\/v2\/tags?post=15072"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}