为“私有静态只读”字段创建存根

Creating stub for `private static readonly` field

由于 Improper Instantiation problem 建议创建 private static readonlyHttpClient 实例。

由于时间不够,我将 mocked client 注入到测试方法中,并以 client 作为参数。

问题是我如何以简单的方式将 mock 注入 SingleHttpClientInstanceControllerprivate static readonly HttpClient 字段?

how can I in simple way inject mock into private static readonly HttpClient field of SingleHttpClientInstanceController?

答:没有简单的方法。

建议:

抽象访问器后面的资源

public interface IHttpClientAccessor {
    HttpClient HttpClient { get; }
}

并将其注入依赖控制器。

public class SingleHttpClientInstanceController : ApiController {
    private readonly HttpClient HttpClient;

    public SingleHttpClientInstanceController(IHttpClientAccessor httpClientAccessor) {
        HttpClient = httpClientAccessor.HttpClient;
    }

    // This method uses the shared instance of HttpClient for every call to GetProductAsync.
    public async Task<Product> GetProductAsync(string id) {
        var hostName = HttpContext.Current.Request.Url.Host;
        var result = await HttpClient.GetStringAsync(string.Format("http://{0}:8080/api/...", hostName));
        return new Product { Name = result };
    }
}

访问 HttpContext 也应该做同样的事情,这是最近在 Asp.Net-Core 的 IHttpContextAccessor

中引入的

IHttpClientAcessor 的实现看起来像这样

public class HttpClientAccessor : IHttpClientAccessor {
    static readonly Lazy<HttpClient> client = new Lazy<HttpClient>(() => new HttpClient());
    public HttpClient HttpClient { get { return client.Value; } }
}

所以现在对于测试,您可以注入依赖项的模拟。

如果使用 DI 容器,请记得将访问器也注册为单例。