# Apprentice Dev Blog: Week 4 - Repositories and Testing
> Our 2022 apprentice has been working on adding unit tests and implementing the repository pattern this week.

*11 June 2022*


The cover image for this post is by [Girl with red hat](https://unsplash.com/photos/ZOdMHFZ0HkM)


---

This blog post was written by Alex..  Alex is our apprentice for 2022, and will be providing frequent developer logs.


Jamie here - to jump directly to Alex's log for this week, click [here](#alex's-devlog)

Today marks the completion of Alex's fourth week with us, meaning that they are halfway through their apprenticeship.

remember that Alex is NOT their real name


Alex is studying a Digital [T-Level course](https://www.gov.uk/government/publications/introduction-of-t-levels/introduction-of-t-levels) and has joined us for their mandatory eight weeks in industry.

We are incredibly proud to be helping with Alex's technical education. And as a reminder, I was assigned to be their PM on the project that they are working on and someone to reach out to for help in completing it. The Digital T-Level course that Alex has taken is very comprehensive and covers a number of different development technologies, but there are certain gaps in their knowledge. This is not meant as a negative point towards either the course designers or those who are delivering it, there is simply not enough time to teach all of the things required of a developer in just two short years.

in fact, development is one of the career choices which require a person to be [constantly learning new things](/tags/career-advice/)


This week I wanted to introduce unit testing, mocking (sometimes called faking), and the [repository pattern](https://deviq.com/design-patterns/repository-pattern).

As a reminder, we started a project with the following goal in mind:

> Let's start with Framework, then move to modern .NET. And if there's time, we'll investigate [.NET Maui](https://docs.microsoft.com/en-us/dotnet/maui/what-is-maui).
>
> — Jamie


We're still working with WinForms right now, and that's primarily because:

1. Alex has familiarity with WinForms
1. Modern .NET supports it
1. (most importantly) there's 20+ years of documentation and examples out there

Anyone who has had to build a new project will know the pain of not having documentation for their chosen technology. So, for now, we're sticking with WinForms _because_ there's 20+ years of documentation, blog posts, Stack Overflow questions, and YouTube videos for Alex to fall back on if I'm not around to help.

One thing which was pointed out by our friend [Scott Harden](https://swharden.com/about/) is that:

> .NET Maui really is at the bleeding edge, and there isn't that much documentation out there - and what there is is partially incorrect **because** it's so new. My recommendation would be to go WPF first, **then** .NET Maui.
>
> — Scott


And that's quite a good point, actually. Especially seeing the number of [issues raised against .NET Maui](https://github.com/dotnet/maui/issues) right now

at the time of writing, the number of open issues stands at 1,213


As such, we'll only migrate the UI to .NET Maui once it's a little more stable, after stopping by WPF or a web-based technology first.

Anyway, you didn't come here to read what I have to say. So here is a development log which represents Alex's fourth week, in their own words:

one note, I've edited for presentation not content


---

## Alex's Devlog


Hi, I'm Alex and am currently studying a Digital T-Level course, am taking my industry experience with RJJ Software, and these are some of the things that I learned this week.

The first thing we did this week was take a look at the project layout. Before we started working this week, my project had the following layout:

![A class diagram showing a simplified view of the relationships between the four major components of the system that Alex is building. This image shows that the UserInterface depends on an interface called IBusinessLogic, which is implemented by a class called BusinessLogic. The BusinessLogic class depends on a database context called DbContext.](/images/blog/apprentice-dev-blog/week-four/original-class-diagram-medium.jpg)


In the above image, the UserInterface depends on an interface called IBusinessLogic, which is implemented by a class called BusinessLogic. The BusinessLogic class depends on a database context called DbContext. This is a standard [nTier architecture design](https://docs.microsoft.com/en-us/azure/architecture/guide/architecture-styles/n-tier), however it meant that if we wanted to write unit tests for the BusinessLogic, we would need to inject the DbContext class with a real database into our tests.

This is perfectly doable, but an easier way to do this would be to add an extra layer using the Repository Pattern, and inject that. That way, we solve two problems:

- the BusinesLogic layer no longer depends on the DbContext (and EntityFramework)
- we can easily mock an IRepository interface

Since we wanted to focus on the S, I, and D parts of SOLID

Jamie here: Single responsibility, Interface segregation, and Dependency inversion


we needed to insert a new interface and class between the BusinessLogic and the DbContext. This would use the [repository pattern](https://deviq.com/design-patterns/repository-pattern) and look like this:

![A class diagram showing a simplified view of the relationships between the four major components of the system that Alex is building. This image shows that the UserInterface depends on an interface called IBusinessLogic, which is implemented by a class called BusinessLogic. The BusinessLogic class depends on an interface called IRepository, which is implemented by a class called Repository. The Repository depends on a database context called DbContext.](/images/blog/apprentice-dev-blog/week-four/target-class-diagram-medium.jpg)


This is a very subtle difference, and one which may look like we're just pushing the database context further down the class hierarchy. And that's precisely what we're doing. We need to push the database context as far away from the business logic as we can. This is because the business logic should have no knowledge of how the data is stored - it's only job is to do business things.

This is part of a approach called [Domain-Driven Design](https://martinfowler.com/bliki/DomainDrivenDesign.html) (DDD). We aren't using DDD to build this system, but it's principles are quite useful in that they help us with our ultimate aim: mock the thing that the business logic uses to write to the database.

## Implementing the Repository Pattern


So the first thing I had to do was create a new interface called `IRepository` with only two methods:

``` csharp
public interface IRepository<T> where T : class
{
    int Add(T item);
    List<T> GetAll();
}
```

This interface uses a couple of techniques:

- [Generics](https://docs.microsoft.com/en-us/dotnet/standard/generics) (i.e. the `<T>` part)
- [Constraints](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters) (i.e. the `where T : class` part)

This interface will apply to any type T which is a class - this means that it won't apply to `struct` types, but we don't need that. Entity Framework is doing the hard work of converting all of our database rows into classes, so this work perfectly as a generic wrapper around the DbContext.

Jamie here: a potential refactor here would be to have all of our database table classes inherit from a known base class, then change the constraint to that base class. This will reduce the chances of the IRepository being used for something that the DbContext doesn't know about


The `Repository` class needs a little wiring up in order to fully implement the `IRepository` interface. This is what it looks like:

```csharp
public class Repository<T> : IRepository<T> where T : class
{
    private readonly AlexProjectDbContext _dbContext;
    private DbSet<T> entities;

    public Repository(AlexProjectDbContext dbContext)
    {
        _dbContext = dbContext;
        entities = dbContext.Set<T>();
    }

    public int Add(T item) 
    {
        entities.Add(item);
        return _dbContext.SaveChanges();
    }

    public List<T> GetAll()
    {
        return entities.ToList();
    }
}
```

Taking this a step at a time:

```csharp
private readonly AlexProjectDbContext _dbContext;

public Repository(AlexProjectDbContext dbContext)
{
    _dbContext = dbContext;
}
```

We've seen this elsewhere, it's .NET's dependency injection working for us. We'll need to alter the composition root, but this will continue to work well for us. The other private property is a little different:

```csharp
private DbSet<T> entities;

public Repository(AlexProjectDbContext dbContext)
{
    _dbContext = dbContext;
    entities = dbContext.Set<T>();
}
```

The `entities` property will allow us to operate on the `dbContext`'s datasets for the `T` constraint. This means that if `T` where set to `SomeAmazingDatabaseClass` then the entities would be working with the `DbSet<SomeAmazingDatabaseClass>` which needs to be exposed as a public property of the underlying DbContext.

This allows us to only ever expose the entities that we need for the repository to work, without ever modifying the underlying DbContext. Which brings us to the O part of SOLID:

- Open for extension, closed for modification

 Jamie here: this isn't a perfect example of the O principle, but it will work for what Alex is putting across


A little rewiring later, and our BusinessLogic classes start to look like this:

```csharp
public interface IService
{
    int CreateNewThing(string name, string address /* etc */);
}

public class ImplementsServiceInterface : IService
{
    private readonly IRepository<SomeAmazingDatabaseClass> _repository;
    
    public ImplementsServiceInterface(IRepository<SomeAmazingDatabaseClass> repository)
    {
        _repository = repository;
    }

    public int CreateNewThing(string name, string address /* etc */)
    {
        return _repository.Add(new SomeAmazingDatabaseClass(name, address /* etc */));
    }
// ... methods here
}
```

Note that we haven't yet changed the composition root, so this will not compile - even if it wasn't a trivialised example. So let's do that now.

Remember that our composition root is at the very start of the program - in the Program.cs. We need to change the way that the services are wired up from:

```csharp
private static void ConfigureServices(IServiceCollection services, string connectionString)
{
    services
        .AddTransient<StartScreen>()
        .AddTransient<IService, ImplementsServiceInterface>()

        // And this is where we inject the DbContext
        .AddDbContext<AlexProjectDbContext>(options => options.UseSqlServer(connectionString));
}
```

to:

```csharp
private static void ConfigureServices(IServiceCollection services, string connectionString)
{
    services
        .AddTransient<StartScreen>()
        .AddTransient<IService, ImplementsServiceInterface>()

        // Inject our IRepository BEFORE the Database Context
        .AddTransient(typeof(IRepository<>), typeof(Repository<>))
        .AddDbContext<AlexProjectDbContext>(options => options.UseSqlServer(connectionString));
}
```

The line that we've added:

```csharp
.AddTransient(typeof(IRepository<>), typeof(Repository<>))
```

is doing something very complex. It's using the [typeof operator](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast#typeof-operator) to get type data about the `IRepository` and `Repository` classes _WITHOUT_ the constraint (i.e the `where T : class`) or the generic rule (i.e. the `<T>`). This line is saying to the .NET dependency injector:

> Whenever I ask for a type which matches the type definition of `IRepository`, regardless of the constraint, give me a matching `Repository` with a matching constraint


So if we ask for an `IRepository<string>` (as a silly example), the .NET dependency injection framework will new up an instance of a `Repository<string>` class and all of it's dependencies, and pass that in

Jamie here: again, this is a silly example as you wouldn't have a `DbSet<string>`; but it get's the point across 


With all of that in place, and some rewriting of the services, I was able to start looking into writing unit tests and mocking all of the dependencies for the services.

## Mocking and Unit Tests


The services found in the Business Logic layer need to be tested, but we don't want to be injecting a real-life database into the services in order to test them. If we did, then we'd risk polluting the database that the live application points at - and we don't want a real user of the system finding our test data

Jamie here: it's more than a little embarrassing to have a user report that there's a &quot;Testy McTestface&quot; entry in their reports


So for unit testing, we want to mock (sometimes called fake) our dependencies. This is one of the reasons we've been developing against interfaces: so that we can swap out the concrete implementation (in our instance the `Repository<T>` class) for one with methods which we know will return specific data.

This is where [moq](https://moq.github.io/moq4/) comes in. moq is a library which allows us to mock the method calls of a given interface

Jamie here: it also works with classes, but I've never used it for that


Let's say that we have an interface which looks like this:

```csharp
// our trusty old IRepository interface
public interface IRepository<T> where T : class
{
    int Add(T item);
    List<T> GetAll();
}
```

And that we have a class which makes use of the `IRepository`, like this:

```csharp
public class ImplementsServiceInterface : IService
{
    private readonly IRepository<SomeAmazingDatabaseClass> _repository;
    
    public ImplementsServiceInterface(IRepository<SomeAmazingDatabaseClass> repository)
    {
        _repository = repository;
    }

    public int CreateNewThing(string name, string address /* etc */)
    {
        // Do some stuff
        var newDatabaseEntity = new SomeAmazingDatabaseClass(name, address /* etc */);
        // Do some more stuff

        // Call the Add method of the IRepository<SomeAmazingDatabaseClass>
        return _repository.Add(newDatabaseEntity);
    }
}
```

And that we wanted to test that the `CreateNewThing` method did what we wanted it to. We could mock the `Add()` method of the `IRepository<SomeAmazingDatabaseClass>` and tell it to return a given value based on what is passed into it.

Here's what I mean (with some inline comments explaining what's happening):

```csharp
[Fact]
public void Call_CreateNewThing_Expect_int_With_Specific_Value_Returned()
{
    // Arrange

    // Create some random input data
    var name = Guid.NewGuid().ToString();
    var address = Guid.NewGuid().ToString();

    // Make a note of our expected return value
    var expectedReturnValue = 1;

    // Mock the IRepository<SomeAmazingDatabaseClass>
    // This creates an in-memory facade class which implements the
    // IRepository<SomeAmazingDatabaseClass> interface. But the
    // key thing is that we can control what the methods on the
    // facade can return for given inputs
    var mockedRepo = new Mock<IRepository<SomeAmazingDatabaseClass>>();

    // Here we are setting up the Add method on the facade. We're
    // saying, whenever ANY instance of the SomeAmazingDatabaseClass
    // is passed into the facade's Add method, return the integer value 1
    mockedRepo.Setup(x =>
        x.Add(It.IsAny<SomeAmazingDatabaseClass>)
        ).Returns(expectedReturnValue);

    // We want to test a real instance of the ImplementsServiceInterface
    // class, so we create one and pass in all of it's dependencies.
    // If the class had more than one dependency we would pass them in,
    // but this class only has one dependency - and we're providing the
    // object behind the facade of the IRepository<SomeAmazingDatabaseClass>
    var serviceToTest = new ImplementsServiceInterface(mockedRepo.Object);

    // Act

    // Call the real method on the service that we are testing. The
    // key here is to check that the CreateNewThing method doesn't
    // do anything to the result we expect to get out of it.
    var result = serviceToTest.CreateNewThing(name, address);

    // Assert

    // Check that the result of calling the CreateNewThing method
    // matches what we expected it to be
    Assert.Equal(expectedReturnValue, result);
}
```

The above code completely exercises the `CreateNewThing` method on the `ImplementsServiceInterface` without having to worry about _how_ it's dependencies work. This helps us to test one specific part (or unit) of the code at a single time.

But what is a "unit"? A unit is a single piece of code, with all of it's dependencies separated out. Which is why we're only testing a single method in the above test. Some people think that units should be larger than a single method, and some people think that a single method is big enough. Here's a [blog post by Martin Fowler](https://martinfowler.com/bliki/UnitTest.html) on what a unit test is an how big the code that it exercises could be. For my purposes, a single method on one of my services should be complete enough to be classed as a unit.

And with that, I spent the majority of the week working on mocking the dependencies of my services and writing unit tests for them. This gives us two things:

- Confidence that the service does what it should be doing right now
- Confidence that when we swap the user interface out, we don't break anything

---

Jamie again.

I'm really impressed with how much Alex is able to take in and understand. We're doing quite a lot of high level software engineering stuff here, dealing with a number of high level methods exposed by C# and .NET, and generics and constraints. There's really only one (big) thing left to do with Alex's project, and that's migrate from WinForms to .NET Maui.

Last week, I'd mentioned that our friend [Scott Harden](https://swharden.com/about/) said:

> .NET Maui really is at the bleeding edge, and there isn't that much documentation out there - and what there is is partially incorrect **because** it's so new. My recommendation would be to go WPF first, **then** .NET Maui.
>
> — Scott


And that's still a thought which is very much on my mind. But what I'm hoping we can do is take the wonderfully well written [crash course written by Gerald Versluis](https://blog.verslu.is/maui/dotnet-maui-crash-course/) and the incredibly detailed [four hour course by James Montemagno](https://www.youtube.com/watch?v=DuNLR_NJv8U), and build something using both the code that they provide as examples and fall back on their courses to get Alex through the tough parts of building with .NET Maui.

We'll start next week by building a brand new project with .NET Maui which replicates the UI that Alex has already built, but without the services, repositories, and Dbcontext. Once that's in place, we're going to migrate the services, repositories, and DbContext over to the .NET Maui application. And if all goes well, Alex will have a mobile app to go with their desktop app. Oh, and they'll have a Blazor app, too.

I'm not expecting all of that to happen in a week; in fact, I'm estimating that it will take the majority of the rest of Alex's time with us because there will likely be pitfalls with using something so early in it's lifetime. But if they complete the migration to .NET Maui, there's plenty of holes to plug in the application logic.

