0

I'm using: MSTest, Entity Framework 6, and Moq

I'm trying to learn TDD with our preexisting entity framework asp.net application. Right now I'm working in our web api, I created a fresh test project and class and I'm trying to write a test just to see if I can get at least one value back. So in some places I am obviously having to write tests for code that is already in place.

Here I can't figure out if/how to set up my test project, class, or method (not sure which needs setup) in order to test this method

[HttpGet]
[ResponseType(typeof(IEnumerable<TimeZoneDTO>))]
[Route("api/timezone")]
public IHttpActionResult GetTimeZones()
{
    var _out = new IEnumerable<TimeZoneDTO>();
    using (var db = new Entities())
    {
        _out = from x in db.Timezones
               orderby x.UTCOffSet descending
               select new TimeZoneDTO() {
                   Caption = x.Name,
                   Id = x.Abbreviation
               };
    }

    return Ok(_out);
}

The problem is that using (var db = new Entities()) is dependent on a named database configuration string in the web.config file of the controller's project.

public partial class Entities : DbContext
{
    public Entities(): base("name=Entities") {}

    ...
}

What are my options here? Is there a way to get Moq to handle this or do I need to update the test project somehow? What I don't want to do (at this point) is rework something that is going to make me have to change other core parts of the application.

Jmaurier
  • 767
  • 2
  • 10
  • 28
  • Can't you defined the connection string in the `app.config` file of your unit test project? – Progman May 04 '20 at 19:22
  • 3
    It seems that your application lacks a little bit of dependency injection, so it would be hard to cover it with proper unit tests. – Guru Stron May 04 '20 at 19:25
  • 1
    Also i would say that you don't need to move your `_out` variable to outer scope. Just materialize the query with `ToList` inside your `using` block ad move `return` statement there also. – Guru Stron May 04 '20 at 19:28

1 Answers1

1

The typical way to handle situations like this is to change the class that you're testing so that it injects either the DbContext itself or a factory that produces the DbContext. That way, rather than newing up the DbContext on its own, it relies on the Dependency Injection configuration to determine how the DbContext is created. Then you can mock the DbContext (using a mock or fake factory, if you go the Factory route).

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • Thanks, @StriplingWarrior. Does that also mean that the DbContext will get cleaned up automatically without placing it in a using block? – Jmaurier May 04 '20 at 21:43
  • 1
    If you take the Factory approach, you'll still want to use a `using` block to dispose the DbContext that gets created. If you inject the DbContext directly, you'll want to configure your Dependency Injection framework to handle its lifetime. Typically in this model the lifetime should be request- or async-scoped, so a single context gets created at the beginning of a web request, reused by all classes in that request, and disposed at the end of it. – StriplingWarrior May 04 '20 at 22:40