Need Integration Testing crash course

Solarion

Honorary Master
Joined
Nov 14, 2012
Messages
28,050
Reaction score
17,804
Hi guys. I have a great opportunity that has come up, one of those once in a lifetime types. This has been a multiple project assignment and the biggest, worst parts are over. One remains. A small API project that I need to create and run some XUnit Integration tests against. I have never done this.

I gather that the idea of these tests against an API is to test if the commands sent to an API have performed exactly as they should. Any pointers would be greatly appreciated.
 
Please can I get some advice from you guys.

One of the parts of this is to create a small .NET Core API which works with Employees and Jobs. There will be two controllers.

The catch of this is there is no database, nothing. Everything must be persisted in memory such as a Dictionary for collections. When the project is closed, all of the data is lost which is fine!

I wouldn't mind using a Repository pattern for this or something that can persist all of the data for the duration that the project is active.

What would you guys advise on doing something like that? Much appreciated.

Just to show I've been trying something, I've made a start on the base repo itself. Not sure if this is good or a bad approach.

C#:
public class BaseRepository<T> : Repository<T> where T : class
{
    public BaseRepository()
    {
        this.context = new Dictionary<int, T>();
    }
    public override T Get(int id)
    {
        if (!context.ContainsKey(id))
            return null;
        return context[id];
    }

    public override ICollection<T> GetAll()
    {
        return context.Values;
    }

    public override int Insert(T entity)
    {
        entity.GetType().GetProperty("Id").SetValue(entity, context.Count + 1);
        context.Add(context.Count + 1, entity);
        return context.Count;
    }

    public override void Update(int id, T entity)
    {
        this.Delete(id);
        context.Add(id, entity);
    }

    public override void Delete(int id)
    {
        context.Remove(id);
    }
}
 
Please can I get some advice from you guys.

One of the parts of this is to create a small .NET Core API which works with Employees and Jobs. There will be two controllers.

The catch of this is there is no database, nothing. Everything must be persisted in memory such as a Dictionary for collections. When the project is closed, all of the data is lost which is fine!

I wouldn't mind using a Repository pattern for this or something that can persist all of the data for the duration that the project is active.

What would you guys advise on doing something like that? Much appreciated.
Just use the InMemory provider instead of the SQL provider with EF.
 
FYI, dictionary can be “upserted” using “dictionary[key] = value;”, so you don’t need that delete/insert implementation of update
 
Btw is this not what was meant by integration testing?


MS seems have redefined their meaning of integration testing to mean end-to-end tests which others may refer to as functional tests.

Rightly or wrongly, I personally don't "bother" with "API tests" (whatever we want to call these)

100% of my controllers look like the following:

C#:
public async Task<ActionResult> GetSomeData()
{
    var result = await _mediator.Send(new GetSomeData.Query());
    return result.Match<ActionResult>(Ok, NotFound);
}

public async Task<ActionResult> ModifySomeData()
{
    await _mediator.Send(new ModifySomeData.Command());
    return Ok();
}

So basically I only do "unit tests", with an in-memory database, and wiremock standalone for any 3rd party integrations - I call them "feature tests"

Still gives us close to 100% coverage (if you care about coverage), and they are extremely fast - no need to bootstrap the application, and the test results are an as-close-to-accurate representation of the system as we need.

Obviously, what this won't pick-up are things like custom JSON converters


/sits back and waits for "you're an idiot, you don't know what you are doing. I would never work at a company like that" comments :cool:
 
Btw is this not what was meant by integration testing?

It is part of the solution to this API. I misunderstood the original requirements and ran it off of a database but in fact they wanted it to run in memory.

Going to be working flat out on this tonight so may have another question with regards to testing this thing. I've adopted Fluent for testing as it seems to be the standard and easy to use.
 
One of the questions I have is about the end points. I have the choice to upgrade them as I see fit.

Example this is one of the API endpoints to test against. I've been tasked with upgrading it too, to make it more adherent to modern standards.

Now I am obviously not happy with the main problem here, throwing exceptions as opposed to a NotFound return type.

Here is the catch, in the test requirements they say:

- Please do not modify the API contract
- Do not rename the exposed model's properties
- Do not modify the API routes

So am I able to return this as an ActionResult/IAction result and still adhere to those requirements?

C#:
[HttpGet]
[Route("{OrderId:int}")]
public async Task<OrderViewModel> Get(int orderId)
{
    var order = await _orderService.GetOrderById(orderId);

    if(order == null)
    {
        throw new ApplicationException("Not Found");
    }

    return Mapper.Map<OrderViewModel>(order);
}
 
One of the questions I have is about the end points. I have the choice to upgrade them as I see fit.

Example this is one of the API endpoints to test against. I've been tasked with upgrading it too, to make it more adherent to modern standards.

Now I am obviously not happy with the main problem here, throwing exceptions as opposed to a NotFound return type.

Here is the catch, in the test requirements they say:

- Please do not modify the API contract
- Do not rename the exposed model's properties
- Do not modify the API routes

So am I able to return this as an ActionResult/IAction result and still adhere to those requirements?

C#:
[HttpGet]
[Route("{OrderId:int}")]
public async Task<OrderViewModel> Get(int orderId)
{
    var order = await _orderService.GetOrderById(orderId);

    if(order == null)
    {
        throw new ApplicationException("Not Found");
    }

    return Mapper.Map<OrderViewModel>(order);
}

Can move the route string into httpget and remove route?

I don’t think that changing to “IActionResult” is “more modern”, but definitely makes sense IMO

Returning 404 is definitely “correct”, assuming this throws a default 500.
 
One of the questions I have is about the end points. I have the choice to upgrade them as I see fit.

Example this is one of the API endpoints to test against. I've been tasked with upgrading it too, to make it more adherent to modern standards.

Now I am obviously not happy with the main problem here, throwing exceptions as opposed to a NotFound return type.

Here is the catch, in the test requirements they say:

- Please do not modify the API contract
- Do not rename the exposed model's properties
- Do not modify the API routes

So am I able to return this as an ActionResult/IAction result and still adhere to those requirements?

C#:
[HttpGet]
[Route("{OrderId:int}")]
public async Task<OrderViewModel> Get(int orderId)
{
    var order = await _orderService.GetOrderById(orderId);

    if(order == null)
    {
        throw new ApplicationException("Not Found");
    }

    return Mapper.Map<OrderViewModel>(order);
}
tbh if you introduce a 404 response, you’ve essentially broken the API contract.
I don’t see how you can ‘modernise’ without changing the contact.
 
Can move the route string into httpget and remove route?

I don’t think that changing to “IActionResult” is “more modern”, but definitely makes sense IMO

Returning 404 is definitely “correct”, assuming this throws a default 500.

Not going to chance touching that route, don't want to irritate them. It does make more sense yes. I think they made it awful like this on purpose to see what the candidate is going to do.
 
tbh if you introduce a 404 response, you’ve essentially broken the API contract.
I don’t see how you can ‘modernise’ without changing the contact.

Yeah. I don't see how. I presume this section of this test is to see if you will follow strict instructions despite knowing they are wrong.
 
Not going to chance touching that route, don't want to irritate them. It does make more sense yes. I think they made it awful like this on purpose to see what the candidate is going to do.
Not sure what you mean

[HttpGet("{OrderId:int}")]
 
Not sure what you mean

[HttpGet("{OrderId:int}")]

I know right? I could but just going to leave it as they have it. Just writing a couple of tests to handle their great way of throwing errors LOL. Got about 12 of these endpoints.
 
Top
Sign up to the MyBroadband newsletter
X