It’s time to dive into the code!
To keep things simple, we’ll be testing a slightly modified version of the famous Visual Studio Weather Forecast web API template.
Here’s the code:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
private readonly IWeatherService _weatherService;
public WeatherForecastController(IWeatherService weatherService, ILogger<WeatherForecastController> logger)
{
_weatherService = weatherService;
_logger = logger;
}
[HttpGet("{city}")]
public IActionResult Get(string city)
{
IEnumerable<WeatherForecast> data = _weatherService.GetByCity(city);
if (data.Any())
return Ok(data);
_logger.LogInformation("No data found for {City}", city);
return NoContent();
}
}
Although we’re not doing TDD here, it’s important to understand that if we were, we’d test this controller using the London school of TDD. This approach is outside-in and behavior-driven.
The key idea is this: we don’t care how the concrete implementation of the WeatherService works or what it does.
The only thing we know — and care about — is that it returns an IEnumerable<WeatherForecast>
. That’s enough for us! In fact, we won’t create a concrete implementation of the IWeatherService
interface at all.
Here’s what the IWeatherService
interface looks like:
public interface IWeatherService
{
IEnumerable<WeatherForecast> GetByCity(string city);
}
And here’s the WeatherForecast
class that comes pre-generated by Visual Studio:
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
With this setup, we’re ready to start testing! First, we’ll explore how to test using Dummy, Stub, Spy, and Mock objects. Later, we’ll dive into powerful libraries like Moq, AutoFixture, and AutoFixture.AutoMoq to streamline our tests.
We won’t consider using a Fake as a Test Double in our examples. Typically, Fakes include logic to simplify complex systems, such as an in-memory database replacing a real database. However, given the simplicity of the code we’re testing, creating a simplified implementation of IWeatherService
would be unnecessary and out of scope.
What’s Next?
In the next article, we’ll test this controller with:
A Dummy logger, because we’ve decided that “we don’t care” about the logging part.
A Stub WeatherService, which will help us simulate the behavior of the
IWeatherService
.
Stay tuned!
Top comments (0)