• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Aldaviva / Unfucked / 23378719444

21 Mar 2026 11:27AM UTC coverage: 41.876% (+6.4%) from 35.442%
23378719444

push

github

Aldaviva
Restore ability to mock UnfuckedHttpClient class not using interfaces by making SendAsync(HttpRequest,CancellationToken) virtual

646 of 1629 branches covered (39.66%)

0 of 2 new or added lines in 2 files covered. (0.0%)

1152 of 2751 relevant lines covered (41.88%)

162.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/HTTP/HttpRequest.cs
1
using Unfucked.HTTP.Config;
2

3
namespace Unfucked.HTTP;
4

5
public readonly record struct HttpRequest(HttpMethod Verb, Uri Uri, IEnumerable<KeyValuePair<string, string>> Headers, HttpContent? Body, IClientConfig? ClientConfig) {
×
6

7
    public static async Task<HttpRequest> Copy(HttpRequestMessage original) {
8
        IEnumerable<KeyValuePair<string, string>> replayedHeaders = original.Headers.SelectMany(header => header.Value.Select(val => new KeyValuePair<string, string>(header.Key, val)));
×
9

10
        HttpContent? replayedRequestBody = null;
×
11
        if (original.Content is {} originalBody) {
×
12
            MemoryStream replayedRequestBodyStream = new();
×
13
            // CopyToAsync may fail if the original stream isn't seekable, in which case we should buffer all request bodies before their original request is sent
14
            await originalBody.CopyToAsync(replayedRequestBodyStream).ConfigureAwait(false);
×
15
            replayedRequestBody = new StreamContent(replayedRequestBodyStream);
×
16
            foreach (KeyValuePair<string, IEnumerable<string>> originalRequestBodyHeader in originalBody.Headers) {
×
17
                replayedRequestBody.Headers.Add(originalRequestBodyHeader.Key, originalRequestBodyHeader.Value);
×
18
            }
19
        }
×
20

NEW
21
        return new HttpRequest(original.Method, original.RequestUri!, replayedHeaders, replayedRequestBody, null);
×
22
    }
×
23

24
    /*
25
     * These crappy methods are only used for testing, so some are synchronous and inefficient
26
     */
27
    public bool Equals(HttpRequest other) =>
28
        Verb.Equals(other.Verb) &&
×
29
        Uri.Equals(other.Uri) &&
×
30
        Headers.Count() == other.Headers.Count() &&
×
31
        new HashSet<KeyValuePair<string, string>>(Headers, HeaderNameEqualityComparer.INSTANCE).SetEquals(new HashSet<KeyValuePair<string, string>>(other.Headers,
×
32
            HeaderNameEqualityComparer.INSTANCE)) &&
×
33
        ((Body is null && other.Body is null) ||
×
34
            (Body is not null && other.Body is not null && (SerializeBodySync()?.Equals(other.SerializeBodySync(), StringComparison.InvariantCulture) ?? true)));
×
35

36
    public override int GetHashCode() {
37
        unchecked {
38
            int hashCode = Verb.GetHashCode();
×
39
            hashCode = (hashCode * 397) ^ Uri.GetHashCode();
×
40
            hashCode = (hashCode * 397) ^ Headers.GetHashCode();
×
41
            hashCode = (hashCode * 397) ^ (Body != null ? Body.GetHashCode() : 0);
×
42
            return hashCode;
×
43
        }
44
    }
45

46
    public override string ToString() =>
47
        $"""
×
48
        {Verb} {Uri}
×
49
        {Headers.Select(pair => $"{pair.Key}: {pair.Value}").Join('\n')}
×
50

×
51
        {SerializeBodySync()}
×
52
        """;
×
53

54
    private string? SerializeBodySync() => Body?.ReadAsStringAsync().GetAwaiter().GetResult();
×
55

56
    private sealed class HeaderNameEqualityComparer: IEqualityComparer<KeyValuePair<string, string>> {
57

58
        public static readonly HeaderNameEqualityComparer INSTANCE = new();
×
59

60
        public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y) {
61
            return string.Equals(x.Key, y.Key, StringComparison.InvariantCultureIgnoreCase);
×
62
        }
63

64
        public int GetHashCode(KeyValuePair<string, string> obj) {
65
            return StringComparer.InvariantCultureIgnoreCase.GetHashCode((object) obj.Key);
×
66
        }
67

68
    }
69

70
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc