Building microservices through Event Driven Architecture part3: Presenters, Views, and Controllers
This tutorial is the 3rd part of a series : Building microservices through Event Driven Architecture
During this journey, I will implement the command side of Presenters, Views, and Controllers
- LogCorner.EduSync.Speech.Presentation
In this step, I will implement the presentation. Here, the presentation is not the user interface but the Web API.
It is also possible to implement the repository first, before the presentation, the order does not matter.
Note that it will be necessary to configure the dependency injection later on.
IUnitOfWork and ISpeechRepository are injected into RegisterSpeechUseCase. Therefore, IUnitOfWork and ISpeechRepository must be instantiated to get an instance of IRegisterSpeechUseCase
like this
But , since I am doing a mock of IRegisterSpeechUseCase, I still do not need a concrete implementation of IUnitOfWork and ISpeechRepository.
So I will configure the dependency injections when my repository is implemented and ready to use.
This is useful when one team is working on the presention and another team is working on the repository. In this case every team can advance on his side without waiting for other team’s
Presentation belongs to interface adapter in the clean architecture
Interface Adapters
The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web. It is this layer, for example, that will wholly contain the MVC architecture of a GUI. The Presenters, Views, and Controllers all belong in here. The models are likely just data structures that are passed from the controllers to the use cases, and then back from the use cases to the presenters and views.
Here, I have to create an HttpPost action that accepts a dto, which contains information about the speech I want to create.
If this information is correct, I call the handle function of my usecase and I pass it as argument this dto converted into command. If informations into the dto are not correct I return BadRequest or 400
Then , usecase executes, and if everything is Ok, I return 200 otherwise, I return 500
So my first test will be : Register Speech With Invalid ModelState Return BadRequest
So let us create it
The next step is to create a SpeechForCreationDto class and a SpeechController class with a post action:
SpeechForCreationDto
SpeechController
then my first test pass
my second test will verify that _registerSpeechUseCase.Handle(command) is called only once and everything is Ok
So, to make the previous test pass, I have to call _registerSpeechUseCase.Handle like this
The last test is to handle InternalServerError (500) if an exception occured
I prefer to create a middlware so as to catch errors globaly, if an exception is thrown I proceed as follow :
- Log the StackTrace logger.LogError($”Something went wrong: {ex.StackTrace}”);
- Return Internal Server Error with StatusCode = 500
I’m using a single try / catch block in the entire application. It is also possible to have no try / catch by doing the following:
Here is the unit test of ExceptionMiddleware
Code Coverage of presentation is 63%:
What is not tested are startup class and Programm class and ExceptionMiddleware.MoveNext() function
I can add more tests to cover them, but I can also leave them like that because they will be covered by the integration tests
Regards
Code source is available here RegisterSpeechPresentation