Controller Method Testing in MVC.Testing (xUnit)
1.Configuration Load Fails
Configuration files like secrets.json
only load in the Development environment.
Make sure the environment is set to "Development"
during testing if required secrets are needed.
2.Logging Output Not Visible
xUnit captures console output, so Console.WriteLine
won't appear in test results by default.
Use ITestOutputHelper
instead. Inject it via the test class constructor like this:
public class MyTests
{
private readonly ITestOutputHelper _output;
public MyTests(ITestOutputHelper output)
{
_output = output;
}
}
3.Adding Authorization Token to Test Requests
If your API requires a Bearer token, set it on the HttpClient
before sending requests:
_client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token.TokenStr);
// Example:
public class TaskControllerTests : IClassFixture<TestingWebApplicationFactory<Program>>
{
private readonly HttpClient _client;
private readonly ITokenHelper _tokenHelper;
private readonly IConfiguration _configuration;
private readonly ITestOutputHelper _output;
public TaskControllerTests(TestingWebApplicationFactory<Program> factory, ITestOutputHelper output)
{
_client = factory.CreateClient();
_tokenHelper = factory.Services.GetRequiredService<ITokenHelper>();
_configuration = factory.Services.GetRequiredService<IConfiguration>();
_output = output;
}
[Fact]
public async Task CreateTaskAsync_ShouldReturnSuccess()
{
// Arrange: JSON request matching CreateTaskRequest shape
var testUserId = "7";
var entry = new
{
UserId = testUserId,
JWTVersion = 1,
};
var token = _tokenHelper.CreateToken(entry, TokenType.AccessToken);
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.TokenStr);
string UUID = Guid.NewGuid().ToString();
var request = new CreateTaskRequest("Test Task" + UUID, "Test Description" + UUID,
DateTime.Today.AddDays(1), 1, "3");
// Act: Call your API route (adjust route prefix if needed)
var response = await _client.PostAsJsonAsync("/Task/CreateTask", request);
// Assert: success status and response content
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
var apiResponse = JsonSerializer.Deserialize<ApiResponse<DataWrapper<string>>>(responseString);
apiResponse.Should().NotBeNull();
apiResponse.data.info.Should().BeEquivalentTo("Task created successfully");
apiResponse.data.code.Should().Be(300000);
}
}
public class TestingWebApplicationFactory<TProgram> : WebApplicationFactory<TProgram> where TProgram : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Testing"); // 设置环境名,方便读取 appsettings.Testing.json
}
}
public class ApiResponse<T>
{
public int code { get; set; }
public string message { get; set; }
public T data { get; set; }
}
public class DataWrapper<T>
{
public int code { get; set; }
public T info { get; set; }
}
What Is WireMock.Net?
WireMock.Net is a tool which mimics the behaviour of an HTTP API, it captures the HTTP requests and sends it to WireMock.Net HTTP server, which is started and as a result, we can setup expectations, call the service and then verify its behaviour.
When Should We Use WireMock.Net?
- HTTP Dependencies Not Ready
- Unit Test classes which use HTTP APIs
- Integration or End-to-end tests using external HTTP APIs
Install:
dotnet add package WireMock.Net.StandAlone
dotnet add package WireMock.Net
//Example:
using System.Net.Http;
using System.Threading.Tasks;
using WireMock.Server;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using Xunit;
public class WeatherServiceTests
{
[Fact]
public async Task GetWeather_ShouldReturnMockedData()
{
// 启动 WireMock 服务器
var server = WireMockServer.Start();
// 配置模拟响应
server.Given(
Request.Create().WithPath("/weather").UsingGet().WithParam("city", "London")
)
.RespondWith(
Response.Create()
.WithStatusCode(200)
.WithHeader("Content-Type", "application/json")
.WithBody("{ \"city\": \"London\", \"temperature\": 20 }")
);
// 使用 HttpClient 发出请求(请求 WireMock 模拟服务)
var client = new HttpClient();
var response = await client.GetAsync($"{server.Urls[0]}/weather?city=London");
var content = await response.Content.ReadAsStringAsync();
// 验证返回内容
Assert.Contains("\"temperature\": 20", content);
server.Stop();
}
}
//
Top comments (0)