Becoming a software developer – episode XII

Becoming a software developer – episode XII

Welcome to the twelfth episode of my course “Becoming a software developer” in which we will write tests, both unit and integration (end-to-end) for our application.

All of the materials including videos and sample projects can be downloaded from here.
The source code repository is being hosted on GitHub.


 

Scope

  • Unit tests
  • Integration tests

Abstract

Unit tests

You can read moe about testing here (the episode VII of this course), so I will not go into the details of this practice here. Instead, I want to tell you what is needed in order to start writing tests for the Passenger app. At first, I decided to use xUnit instead of NUnit, mostly due to the fact that I had some issues related to running NUnit tests after the latest update of the .NET Core framework to the version 1.1.
For the starters, including the following dependencies within the Passenger.Tests.csproj file:

And let’s write a very basic tests – create a new directory called Services and add a new class UserServiceTests containing the following code:

Do not forget about adding the required “using” to the missing namespaces. Eventually, run the dotnet test command and that’s it, your first unit test shall successfully pass!

Integration tests

Unit tests are easy, so what about creating sophisticated integration tests that will execute the real HTTP calls on our API? It could be done twofold – the first way is to run the API using dotnet run and write tests using e.g. HttpClient in order to send requests and validate them by using particular assertions.

However, there’s’ also another way, much cooler than that. Thanks to the ASP.NET Core framework, you can run the whole API in the memory and perform the integration tests this way, which is really cool. You can find more details here, but this is how could it look like.
At first, include the following dependencies within the Passenger.Tests.EndToEnd.csproj file:

And let’s write the actual tests – create a new directory named Controllers and add a new class UsersControllerTests. Having done that, implement the following tests:

As before, make sure you do not forget about adding the required “using” to the missing namespaces. Finally, run the dotnet test command and that’s all!

Next

In the next episode, we’ll talk implement the Command Handler pattern and make use of the external Autofac (which is a powerful IoC container) in order to achieve such goal.

8 Comments Becoming a software developer – episode XII

  1. Pingback: Dew Drop - April 17, 2017 (#2459) - Morning Dew

  2. Tk

    Rzeczywiście artykuł jest bardzo dobry i nawet chciałem spróbować testów integracyjnych tyle, że w pełnym .net i OWIN. Samo uruchomienie aplikacji pod testy nie jest specjalnie trudne, bo składa się do napisania kilka linijek. Problemem jest operowanie na entity framework w pamięci, z którym nie mogłem sobie poradzić. Może jest ktoś w stanie pomóc poprzez link do artykułu lub może sam zna rozwiązanie, bo póki co nie wiem gdzie szukać.
    Pozdrawiam

    Reply
      1. Tk

        No tak EF Core posiada, tylko ja działam pod EF 6(Poprostu śledząc kurs uczę się też .net 4.6, z którego nie czuje się jeszcze pewnie) i tutaj pojawia się ściana(przynajmniej dla mnie) bo dostaje jedynie na czerwono 3 wyjątki 1 z entity i 2 z mscorlib i status code 500.

        Reply
  3. Bartosz

    Zmieniałeś linijkę w pliku Startup.cs z powiązaniem do InMemoryUserRepository? Bo nie widziałem, żebyś go zmieniał z AddScoped na AddSingleton, ani nigdzie nie wspominałeś o tym, a wszystko działa tak jakbyś miał właśnie użyty AddSingleton.
    Patrząc na poprzedni odcinek XI i obecny XII, użycie:
    services.AddScoped();
    prowadzi do tego, że za każdym zapytaniem będzie nowa instancja? InMemoryUserRepository, przez co np. w odcinku XI można było zauważyć, że przy z każdym zapytaniem o tego samego użytkownika jest inne Id, a w obecnym odcinku XII nie przechodzi test given_unique_email_user_should_be_created(), bo są 2 zapytania w jednym teście przez co po utworzeniu użytkownika, chcąc wysłać zapytanie GET o utworzonego użytkownika to on już nie istnieje, a widzę, że u Ciebie wszystko działa tak jak należy, stąd też moje pytanie 🙂

    Reply
    1. Piotr Gankiewicz

      Rejestrujesz interfejs jako singleton lub ustawiasz statyczną kolekcję obiektów w jego implementacji (oczywiście aby to było w pełni bezpieczne odnośnie wielowątkowości należy wybrać typ dedykowany Concurrent).

      Reply
  4. Pingback: Becoming a software developer - episode XIII [PL] - Python In Business Archive

Leave A Comment

Your email address will not be published. Required fields are marked *