OSDN Git Service

IApiConnectionをIApiConnectionLegacyに名前変更
[opentween/open-tween.git] / OpenTween.Tests / Api / TwitterApiTest.cs
index 5a49f42..d74088b 100644 (file)
@@ -38,11 +38,9 @@ namespace OpenTween.Api
     public class TwitterApiTest
     {
         public TwitterApiTest()
-        {
-            this.MyCommonSetup();
-        }
+            => this.MyCommonSetup();
 
-        public void MyCommonSetup()
+        private void MyCommonSetup()
         {
             var mockAssembly = new Mock<_Assembly>();
             mockAssembly.Setup(m => m.GetName()).Returns(new AssemblyName("OpenTween"));
@@ -53,108 +51,101 @@ namespace OpenTween.Api
         [Fact]
         public void Initialize_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                Assert.Null(twitterApi.apiConnection);
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            Assert.Null(twitterApi.ApiConnection);
 
-                twitterApi.Initialize("*** AccessToken ***", "*** AccessSecret ***", userId: 100L, screenName: "hogehoge");
+            twitterApi.Initialize("*** AccessToken ***", "*** AccessSecret ***", userId: 100L, screenName: "hogehoge");
 
-                Assert.IsType<TwitterApiConnection>(twitterApi.apiConnection);
+            Assert.IsType<TwitterApiConnection>(twitterApi.ApiConnection);
 
-                var apiConnection = (TwitterApiConnection)twitterApi.apiConnection;
-                Assert.Equal("*** AccessToken ***", apiConnection.AccessToken);
-                Assert.Equal("*** AccessSecret ***", apiConnection.AccessSecret);
+            var apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!;
+            Assert.Equal("*** AccessToken ***", apiConnection.AccessToken);
+            Assert.Equal("*** AccessSecret ***", apiConnection.AccessSecret);
 
-                Assert.Equal(100L, twitterApi.CurrentUserId);
-                Assert.Equal("hogehoge", twitterApi.CurrentScreenName);
+            Assert.Equal(100L, twitterApi.CurrentUserId);
+            Assert.Equal("hogehoge", twitterApi.CurrentScreenName);
 
-                // 複数回 Initialize を実行した場合は新たに TwitterApiConnection が生成される
-                twitterApi.Initialize("*** AccessToken2 ***", "*** AccessSecret2 ***", userId: 200L, screenName: "foobar");
+            // 複数回 Initialize を実行した場合は新たに TwitterApiConnection が生成される
+            twitterApi.Initialize("*** AccessToken2 ***", "*** AccessSecret2 ***", userId: 200L, screenName: "foobar");
 
-                var oldApiConnection = apiConnection;
-                Assert.True(oldApiConnection.IsDisposed);
+            var oldApiConnection = apiConnection;
+            Assert.True(oldApiConnection.IsDisposed);
 
-                Assert.IsType<TwitterApiConnection>(twitterApi.apiConnection);
+            Assert.IsType<TwitterApiConnection>(twitterApi.ApiConnection);
 
-                apiConnection = (TwitterApiConnection)twitterApi.apiConnection;
-                Assert.Equal("*** AccessToken2 ***", apiConnection.AccessToken);
-                Assert.Equal("*** AccessSecret2 ***", apiConnection.AccessSecret);
+            apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!;
+            Assert.Equal("*** AccessToken2 ***", apiConnection.AccessToken);
+            Assert.Equal("*** AccessSecret2 ***", apiConnection.AccessSecret);
 
-                Assert.Equal(200L, twitterApi.CurrentUserId);
-                Assert.Equal("foobar", twitterApi.CurrentScreenName);
-            }
+            Assert.Equal(200L, twitterApi.CurrentUserId);
+            Assert.Equal("foobar", twitterApi.CurrentScreenName);
         }
 
         [Fact]
         public async Task StatusesHomeTimeline_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterStatus[]>(
-                        new Uri("statuses/home_timeline.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterStatus[]>(
+                    new Uri("statuses/home_timeline.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
                             { "count", "200" },
                             { "max_id", "900" },
                             { "since_id", "100" },
-                        },
-                        "/statuses/home_timeline")
-                )
-                .ReturnsAsync(new TwitterStatus[0]);
+                    },
+                    "/statuses/home_timeline")
+            )
+            .ReturnsAsync(Array.Empty<TwitterStatus>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.StatusesHomeTimeline(200, maxId: 900L, sinceId: 100L)
-                    .ConfigureAwait(false);
+            await twitterApi.StatusesHomeTimeline(200, maxId: new("900"), sinceId: new("100"));
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task StatusesMentionsTimeline_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterStatus[]>(
-                        new Uri("statuses/mentions_timeline.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterStatus[]>(
+                    new Uri("statuses/mentions_timeline.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
                             { "count", "200" },
                             { "max_id", "900" },
                             { "since_id", "100" },
-                        },
-                        "/statuses/mentions_timeline")
-                )
-                .ReturnsAsync(new TwitterStatus[0]);
+                    },
+                    "/statuses/mentions_timeline")
+            )
+            .ReturnsAsync(Array.Empty<TwitterStatus>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.StatusesMentionsTimeline(200, maxId: 900L, sinceId: 100L)
-                    .ConfigureAwait(false);
+            await twitterApi.StatusesMentionsTimeline(200, maxId: new("900"), sinceId: new("100"));
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task StatusesUserTimeline_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterStatus[]>(
-                        new Uri("statuses/user_timeline.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterStatus[]>(
+                    new Uri("statuses/user_timeline.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "screen_name", "twitterapi" },
                             { "include_rts", "true" },
                             { "include_entities", "true" },
@@ -163,58 +154,81 @@ namespace OpenTween.Api
                             { "count", "200" },
                             { "max_id", "900" },
                             { "since_id", "100" },
-                        },
-                        "/statuses/user_timeline")
-                )
-                .ReturnsAsync(new TwitterStatus[0]);
+                    },
+                    "/statuses/user_timeline")
+            )
+            .ReturnsAsync(Array.Empty<TwitterStatus>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.StatusesUserTimeline("twitterapi", count: 200, maxId: 900L, sinceId: 100L)
-                    .ConfigureAwait(false);
+            await twitterApi.StatusesUserTimeline("twitterapi", count: 200, maxId: new("900"), sinceId: new("100"));
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task StatusesShow_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterStatus>(
-                        new Uri("statuses/show.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterStatus>(
+                    new Uri("statuses/show.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "id", "100" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        },
-                        "/statuses/show/:id")
+                    },
+                    "/statuses/show/:id")
+            )
+            .ReturnsAsync(new TwitterStatus { Id = 100L });
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.StatusesShow(statusId: new("100"));
+
+            mock.VerifyAll();
+        }
+
+        [Fact]
+        public async Task StatusesLookup_Test()
+        {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterStatus[]>(
+                    new Uri("statuses/lookup.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
+                        { "id", "100,200" },
+                        { "include_entities", "true" },
+                        { "include_ext_alt_text", "true" },
+                        { "tweet_mode", "extended" },
+                    },
+                    "/statuses/lookup"
                 )
-                .ReturnsAsync(new TwitterStatus { Id = 100L });
+            )
+            .ReturnsAsync(Array.Empty<TwitterStatus>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.StatusesShow(statusId: 100L)
-                    .ConfigureAwait(false);
+            await twitterApi.StatusesLookup(statusIds: new[] { "100", "200" });
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task StatusesUpdate_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterStatus>(
-                        new Uri("statuses/update.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterStatus>(
+                    new Uri("statuses/update.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "status", "hogehoge" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
@@ -224,112 +238,108 @@ namespace OpenTween.Api
                             { "auto_populate_reply_metadata", "true" },
                             { "exclude_reply_user_ids", "100,200" },
                             { "attachment_url", "https://twitter.com/twitterapi/status/22634515958" },
-                        })
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.StatusesUpdate(
+                    "hogehoge",
+                    replyToId: new("100"),
+                    mediaIds: new[] { 10L, 20L },
+                    autoPopulateReplyMetadata: true,
+                    excludeReplyUserIds: new[] { 100L, 200L },
+                    attachmentUrl: "https://twitter.com/twitterapi/status/22634515958"
                 )
-                .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
-
-                twitterApi.apiConnection = mock.Object;
+                .IgnoreResponse();
 
-                await twitterApi.StatusesUpdate("hogehoge", replyToId: 100L, mediaIds: new[] { 10L, 20L },
-                        autoPopulateReplyMetadata: true, excludeReplyUserIds: new[] { 100L, 200L },
-                        attachmentUrl: "https://twitter.com/twitterapi/status/22634515958")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
-
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task StatusesUpdate_ExcludeReplyUserIdsEmptyTest()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterStatus>(
-                        new Uri("statuses/update.json", UriKind.Relative),
-                        new Dictionary<string, string> {
-                            { "status", "hogehoge" },
-                            { "include_entities", "true" },
-                            { "include_ext_alt_text", "true" },
-                            { "tweet_mode", "extended" },
-                            // exclude_reply_user_ids は空の場合には送信されない
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
-
-                twitterApi.apiConnection = mock.Object;
-
-                await twitterApi.StatusesUpdate("hogehoge", replyToId: null, mediaIds: null, excludeReplyUserIds: new long[0])
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
-
-                mock.VerifyAll();
-            }
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterStatus>(
+                    new Uri("statuses/update.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
+                        { "status", "hogehoge" },
+                        { "include_entities", "true" },
+                        { "include_ext_alt_text", "true" },
+                        { "tweet_mode", "extended" },
+                        // exclude_reply_user_ids は空の場合には送信されない
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.StatusesUpdate("hogehoge", replyToId: null, mediaIds: null, excludeReplyUserIds: Array.Empty<long>())
+                .IgnoreResponse();
+
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task StatusesDestroy_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterStatus>(
-                        new Uri("statuses/destroy.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "id", "100" } })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterStatus>(
+                    new Uri("statuses/destroy.json", UriKind.Relative),
+                    new Dictionary<string, string> { { "id", "100" } })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.StatusesDestroy(statusId: 100L)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.StatusesDestroy(statusId: new("100"))
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task StatusesRetweet_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterStatus>(
-                        new Uri("statuses/retweet.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterStatus>(
+                    new Uri("statuses/retweet.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "id", "100" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.StatusesRetweet(100L)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.StatusesRetweet(new("100"))
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task SearchTweets_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterSearchResult>(
-                        new Uri("search/tweets.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterSearchResult>(
+                    new Uri("search/tweets.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "q", "from:twitterapi" },
                             { "result_type", "recent" },
                             { "include_entities", "true" },
@@ -339,192 +349,178 @@ namespace OpenTween.Api
                             { "count", "200" },
                             { "max_id", "900" },
                             { "since_id", "100" },
-                        },
-                        "/search/tweets")
-                )
-                .ReturnsAsync(new TwitterSearchResult());
+                    },
+                    "/search/tweets")
+            )
+            .ReturnsAsync(new TwitterSearchResult());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.SearchTweets("from:twitterapi", "en", count: 200, maxId: 900L, sinceId: 100L)
-                    .ConfigureAwait(false);
+            await twitterApi.SearchTweets("from:twitterapi", "en", count: 200, maxId: new("900"), sinceId: new("100"));
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsOwnerships_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterLists>(
-                        new Uri("lists/ownerships.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterLists>(
+                    new Uri("lists/ownerships.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "screen_name", "twitterapi" },
                             { "cursor", "-1" },
                             { "count", "100" },
-                        },
-                        "/lists/ownerships")
-                )
-                .ReturnsAsync(new TwitterLists());
+                    },
+                    "/lists/ownerships")
+            )
+            .ReturnsAsync(new TwitterLists());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsOwnerships("twitterapi", cursor: -1L, count: 100)
-                    .ConfigureAwait(false);
+            await twitterApi.ListsOwnerships("twitterapi", cursor: -1L, count: 100);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsSubscriptions_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterLists>(
-                        new Uri("lists/subscriptions.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterLists>(
+                    new Uri("lists/subscriptions.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "screen_name", "twitterapi" },
                             { "cursor", "-1" },
                             { "count", "100" },
-                        },
-                        "/lists/subscriptions")
-                )
-                .ReturnsAsync(new TwitterLists());
+                    },
+                    "/lists/subscriptions")
+            )
+            .ReturnsAsync(new TwitterLists());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsSubscriptions("twitterapi", cursor: -1L, count: 100)
-                    .ConfigureAwait(false);
+            await twitterApi.ListsSubscriptions("twitterapi", cursor: -1L, count: 100);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsMemberships_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterLists>(
-                        new Uri("lists/memberships.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterLists>(
+                    new Uri("lists/memberships.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "screen_name", "twitterapi" },
                             { "cursor", "-1" },
                             { "count", "100" },
                             { "filter_to_owned_lists", "true" },
-                        },
-                        "/lists/memberships")
-                )
-                .ReturnsAsync(new TwitterLists());
+                    },
+                    "/lists/memberships")
+            )
+            .ReturnsAsync(new TwitterLists());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsMemberships("twitterapi", cursor: -1L, count: 100, filterToOwnedLists: true)
-                    .ConfigureAwait(false);
+            await twitterApi.ListsMemberships("twitterapi", cursor: -1L, count: 100, filterToOwnedLists: true);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsCreate_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterList>(
-                        new Uri("lists/create.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterList>(
+                    new Uri("lists/create.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "name", "hogehoge" },
                             { "description", "aaaa" },
                             { "mode", "private" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterList()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterList()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsCreate("hogehoge", description: "aaaa", @private: true)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.ListsCreate("hogehoge", description: "aaaa", @private: true)
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsUpdate_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterList>(
-                        new Uri("lists/update.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterList>(
+                    new Uri("lists/update.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "list_id", "12345" },
                             { "name", "hogehoge" },
                             { "description", "aaaa" },
                             { "mode", "private" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterList()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterList()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsUpdate(12345L, name: "hogehoge", description: "aaaa", @private: true)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.ListsUpdate(12345L, name: "hogehoge", description: "aaaa", @private: true)
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsDestroy_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterList>(
-                        new Uri("lists/destroy.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterList>(
+                    new Uri("lists/destroy.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "list_id", "12345" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterList()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterList()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsDestroy(12345L)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.ListsDestroy(12345L)
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsStatuses_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterStatus[]>(
-                        new Uri("lists/statuses.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterStatus[]>(
+                    new Uri("lists/statuses.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "list_id", "12345" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
@@ -533,637 +529,590 @@ namespace OpenTween.Api
                             { "max_id", "900" },
                             { "since_id", "100" },
                             { "include_rts", "true" },
-                        },
-                        "/lists/statuses")
-                )
-                .ReturnsAsync(new TwitterStatus[0]);
+                    },
+                    "/lists/statuses")
+            )
+            .ReturnsAsync(Array.Empty<TwitterStatus>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsStatuses(12345L, count: 200, maxId: 900L, sinceId: 100L, includeRTs: true)
-                    .ConfigureAwait(false);
+            await twitterApi.ListsStatuses(12345L, count: 200, maxId: new("900"), sinceId: new("100"), includeRTs: true);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsMembers_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterUsers>(
-                        new Uri("lists/members.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterUsers>(
+                    new Uri("lists/members.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "list_id", "12345" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
                             { "cursor", "-1" },
-                        },
-                        "/lists/members")
-                )
-                .ReturnsAsync(new TwitterUsers());
+                    },
+                    "/lists/members")
+            )
+            .ReturnsAsync(new TwitterUsers());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsMembers(12345L, cursor: -1)
-                    .ConfigureAwait(false);
+            await twitterApi.ListsMembers(12345L, cursor: -1);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsMembersShow_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterUser>(
-                        new Uri("lists/members/show.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterUser>(
+                    new Uri("lists/members/show.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "list_id", "12345" },
                             { "screen_name", "twitterapi" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        },
-                        "/lists/members/show")
-                )
-                .ReturnsAsync(new TwitterUser());
+                    },
+                    "/lists/members/show")
+            )
+            .ReturnsAsync(new TwitterUser());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsMembersShow(12345L, "twitterapi")
-                    .ConfigureAwait(false);
+            await twitterApi.ListsMembersShow(12345L, "twitterapi");
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsMembersCreate_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUser>(
-                        new Uri("lists/members/create.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUser>(
+                    new Uri("lists/members/create.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "list_id", "12345" },
                             { "screen_name", "twitterapi" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUser()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUser()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsMembersCreate(12345L, "twitterapi")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.ListsMembersCreate(12345L, "twitterapi")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ListsMembersDestroy_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUser>(
-                        new Uri("lists/members/destroy.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUser>(
+                    new Uri("lists/members/destroy.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "list_id", "12345" },
                             { "screen_name", "twitterapi" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUser()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUser()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ListsMembersDestroy(12345L, "twitterapi")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.ListsMembersDestroy(12345L, "twitterapi")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task DirectMessagesRecv_Test()
+        public async Task DirectMessagesEventsList_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterDirectMessage[]>(
-                        new Uri("direct_messages.json", UriKind.Relative),
-                        new Dictionary<string, string> {
-                            { "full_text", "true" },
-                            { "include_entities", "true" },
-                            { "include_ext_alt_text", "true" },
-                            { "count", "200" },
-                            { "max_id", "900" },
-                            { "since_id", "100" },
-                        },
-                        "/direct_messages")
-                )
-                .ReturnsAsync(new TwitterDirectMessage[0]);
-
-                twitterApi.apiConnection = mock.Object;
-
-                await twitterApi.DirectMessagesRecv(count: 200, maxId: 900L, sinceId: 100L)
-                    .ConfigureAwait(false);
-
-                mock.VerifyAll();
-            }
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterMessageEventList>(
+                    new Uri("direct_messages/events/list.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
+                            { "count", "50" },
+                            { "cursor", "12345abcdefg" },
+                    },
+                    "/direct_messages/events/list")
+            )
+            .ReturnsAsync(new TwitterMessageEventList());
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.DirectMessagesEventsList(count: 50, cursor: "12345abcdefg");
+
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task DirectMessagesSent_Test()
+        public async Task DirectMessagesEventsNew_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterDirectMessage[]>(
-                        new Uri("direct_messages/sent.json", UriKind.Relative),
-                        new Dictionary<string, string> {
-                            { "full_text", "true" },
-                            { "include_entities", "true" },
-                            { "include_ext_alt_text", "true" },
-                            { "count", "200" },
-                            { "max_id", "900" },
-                            { "since_id", "100" },
-                        },
-                        "/direct_messages/sent")
-                )
-                .ReturnsAsync(new TwitterDirectMessage[0]);
-
-                twitterApi.apiConnection = mock.Object;
-
-                await twitterApi.DirectMessagesSent(count: 200, maxId: 900L, sinceId: 100L)
-                    .ConfigureAwait(false);
-
-                mock.VerifyAll();
-            }
+            var mock = new Mock<IApiConnectionLegacy>();
+            var responseText = """
+                {
+                  "event": {
+                    "type": "message_create",
+                    "message_create": {
+                      "target": {
+                        "recipient_id": "12345"
+                      },
+                      "message_data": {
+                        "text": "hogehoge",
+                        "attachment": {
+                          "type": "media",
+                          "media": {
+                            "id": "67890"
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+                """;
+            mock.Setup(x =>
+                x.PostJsonAsync<TwitterMessageEventSingle>(
+                    new Uri("direct_messages/events/new.json", UriKind.Relative),
+                    responseText)
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterMessageEventSingle()));
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.DirectMessagesEventsNew(recipientId: 12345L, text: "hogehoge", mediaId: 67890L);
+
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task DirectMessagesNew_Test()
+        public async Task DirectMessagesEventsDestroy_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterDirectMessage>(
-                        new Uri("direct_messages/new.json", UriKind.Relative),
-                        new Dictionary<string, string> {
-                            { "text", "hogehoge" },
-                            { "screen_name", "opentween" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterDirectMessage()));
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.DeleteAsync(
+                    new Uri("direct_messages/events/destroy.json?id=100", UriKind.Relative))
+            )
+            .Returns(Task.CompletedTask);
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.DirectMessagesNew("hogehoge", "opentween")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.DirectMessagesEventsDestroy(eventId: new("100"));
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task DirectMessagesDestroy_Test()
+        public async Task UsersShow_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterDirectMessage>(
-                        new Uri("direct_messages/destroy.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "id", "100" } })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterDirectMessage { Id = 100L }));
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterUser>(
+                    new Uri("users/show.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
+                            { "screen_name", "twitterapi" },
+                            { "include_entities", "true" },
+                            { "include_ext_alt_text", "true" },
+                            { "tweet_mode", "extended" },
+                    },
+                    "/users/show/:id")
+            )
+            .ReturnsAsync(new TwitterUser { ScreenName = "twitterapi" });
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.DirectMessagesDestroy(statusId: 100L)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.UsersShow(screenName: "twitterapi");
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task UsersShow_Test()
+        public async Task UsersLookup_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterUser>(
-                        new Uri("users/show.json", UriKind.Relative),
-                        new Dictionary<string, string> {
-                            { "screen_name", "twitterapi" },
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterUser[]>(
+                    new Uri("users/lookup.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
+                            { "user_id", "11111,22222" },
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        },
-                        "/users/show/:id")
-                )
-                .ReturnsAsync(new TwitterUser { ScreenName = "twitterapi" });
+                    },
+                    "/users/lookup")
+            )
+            .ReturnsAsync(Array.Empty<TwitterUser>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.UsersShow(screenName: "twitterapi")
-                    .ConfigureAwait(false);
+            await twitterApi.UsersLookup(userIds: new[] { "11111", "22222" });
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task UsersReportSpam_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUser>(
-                        new Uri("users/report_spam.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUser>(
+                    new Uri("users/report_spam.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "screen_name", "twitterapi" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUser { ScreenName = "twitterapi" }));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUser { ScreenName = "twitterapi" }));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.UsersReportSpam(screenName: "twitterapi")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.UsersReportSpam(screenName: "twitterapi")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task FavoritesList_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterStatus[]>(
-                        new Uri("favorites/list.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterStatus[]>(
+                    new Uri("favorites/list.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
                             { "count", "200" },
                             { "max_id", "900" },
                             { "since_id", "100" },
-                        },
-                        "/favorites/list")
-                )
-                .ReturnsAsync(new TwitterStatus[0]);
+                    },
+                    "/favorites/list")
+            )
+            .ReturnsAsync(Array.Empty<TwitterStatus>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.FavoritesList(200, maxId: 900L, sinceId: 100L)
-                    .ConfigureAwait(false);
+            await twitterApi.FavoritesList(200, maxId: 900L, sinceId: 100L);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task FavoritesCreate_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterStatus>(
-                        new Uri("favorites/create.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterStatus>(
+                    new Uri("favorites/create.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "id", "100" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.FavoritesCreate(statusId: 100L)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.FavoritesCreate(statusId: new("100"))
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task FavoritesDestroy_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterStatus>(
-                        new Uri("favorites/destroy.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterStatus>(
+                    new Uri("favorites/destroy.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "id", "100" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.FavoritesDestroy(statusId: 100L)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.FavoritesDestroy(statusId: new("100"))
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task FriendshipsShow_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterFriendship>(
-                        new Uri("friendships/show.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "source_screen_name", "twitter" }, { "target_screen_name", "twitterapi" } },
-                        "/friendships/show")
-                )
-                .ReturnsAsync(new TwitterFriendship());
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterFriendship>(
+                    new Uri("friendships/show.json", UriKind.Relative),
+                    new Dictionary<string, string> { { "source_screen_name", "twitter" }, { "target_screen_name", "twitterapi" } },
+                    "/friendships/show")
+            )
+            .ReturnsAsync(new TwitterFriendship());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.FriendshipsShow(sourceScreenName: "twitter", targetScreenName: "twitterapi")
-                    .ConfigureAwait(false);
+            await twitterApi.FriendshipsShow(sourceScreenName: "twitter", targetScreenName: "twitterapi");
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task FriendshipsCreate_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterFriendship>(
-                        new Uri("friendships/create.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "screen_name", "twitterapi" } })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterFriendship>(
+                    new Uri("friendships/create.json", UriKind.Relative),
+                    new Dictionary<string, string> { { "screen_name", "twitterapi" } })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.FriendshipsCreate(screenName: "twitterapi")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.FriendshipsCreate(screenName: "twitterapi")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task FriendshipsDestroy_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterFriendship>(
-                        new Uri("friendships/destroy.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "screen_name", "twitterapi" } })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterFriendship>(
+                    new Uri("friendships/destroy.json", UriKind.Relative),
+                    new Dictionary<string, string> { { "screen_name", "twitterapi" } })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.FriendshipsDestroy(screenName: "twitterapi")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.FriendshipsDestroy(screenName: "twitterapi")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task NoRetweetIds_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<long[]>(
-                        new Uri("friendships/no_retweets/ids.json", UriKind.Relative),
-                        null,
-                        "/friendships/no_retweets/ids")
-                )
-                .ReturnsAsync(new long[0]);
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<long[]>(
+                    new Uri("friendships/no_retweets/ids.json", UriKind.Relative),
+                    null,
+                    "/friendships/no_retweets/ids")
+            )
+            .ReturnsAsync(Array.Empty<long>());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.NoRetweetIds()
-                    .ConfigureAwait(false);
+            await twitterApi.NoRetweetIds();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task FollowersIds_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterIds>(
-                        new Uri("followers/ids.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "cursor", "-1" } },
-                        "/followers/ids")
-                )
-                .ReturnsAsync(new TwitterIds());
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterIds>(
+                    new Uri("followers/ids.json", UriKind.Relative),
+                    new Dictionary<string, string> { { "cursor", "-1" } },
+                    "/followers/ids")
+            )
+            .ReturnsAsync(new TwitterIds());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.FollowersIds(cursor: -1L)
-                    .ConfigureAwait(false);
+            await twitterApi.FollowersIds(cursor: -1L);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task MutesUsersIds_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterIds>(
-                        new Uri("mutes/users/ids.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "cursor", "-1" } },
-                        "/mutes/users/ids")
-                )
-                .ReturnsAsync(new TwitterIds());
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterIds>(
+                    new Uri("mutes/users/ids.json", UriKind.Relative),
+                    new Dictionary<string, string> { { "cursor", "-1" } },
+                    "/mutes/users/ids")
+            )
+            .ReturnsAsync(new TwitterIds());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.MutesUsersIds(cursor: -1L)
-                    .ConfigureAwait(false);
+            await twitterApi.MutesUsersIds(cursor: -1L);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task BlocksIds_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterIds>(
-                        new Uri("blocks/ids.json", UriKind.Relative),
-                        new Dictionary<string, string> { { "cursor", "-1" } },
-                        "/blocks/ids")
-                )
-                .ReturnsAsync(new TwitterIds());
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterIds>(
+                    new Uri("blocks/ids.json", UriKind.Relative),
+                    new Dictionary<string, string> { { "cursor", "-1" } },
+                    "/blocks/ids")
+            )
+            .ReturnsAsync(new TwitterIds());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.BlocksIds(cursor: -1L)
-                    .ConfigureAwait(false);
+            await twitterApi.BlocksIds(cursor: -1L);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task BlocksCreate_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUser>(
-                        new Uri("blocks/create.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUser>(
+                    new Uri("blocks/create.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "screen_name", "twitterapi" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUser()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUser()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.BlocksCreate(screenName: "twitterapi")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.BlocksCreate(screenName: "twitterapi")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task BlocksDestroy_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUser>(
-                        new Uri("blocks/destroy.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUser>(
+                    new Uri("blocks/destroy.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "screen_name", "twitterapi" },
                             { "tweet_mode", "extended" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUser()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUser()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.BlocksDestroy(screenName: "twitterapi")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.BlocksDestroy(screenName: "twitterapi")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task AccountVerifyCredentials_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterUser>(
-                        new Uri("account/verify_credentials.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterUser>(
+                    new Uri("account/verify_credentials.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        },
-                        "/account/verify_credentials")
-                )
-                .ReturnsAsync(new TwitterUser {
-                    Id = 100L,
-                    ScreenName = "opentween",
-                });
+                    },
+                    "/account/verify_credentials")
+            )
+            .ReturnsAsync(new TwitterUser
+            {
+                Id = 100L,
+                ScreenName = "opentween",
+            });
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.AccountVerifyCredentials()
-                    .ConfigureAwait(false);
+            await twitterApi.AccountVerifyCredentials();
 
-                Assert.Equal(100L, twitterApi.CurrentUserId);
-                Assert.Equal("opentween", twitterApi.CurrentScreenName);
+            Assert.Equal(100L, twitterApi.CurrentUserId);
+            Assert.Equal("opentween", twitterApi.CurrentScreenName);
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task AccountUpdateProfile_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUser>(
-                        new Uri("account/update_profile.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUser>(
+                    new Uri("account/update_profile.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
@@ -1171,181 +1120,205 @@ namespace OpenTween.Api
                             { "url", "http://example.com/" },
                             { "location", "Location" },
                             { "description", "&lt;script&gt;alert(1)&lt;/script&gt;" },
-                        })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUser()));
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUser()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.AccountUpdateProfile(name: "Name", url: "http://example.com/", location: "Location", description: "<script>alert(1)</script>")
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.AccountUpdateProfile(name: "Name", url: "http://example.com/", location: "Location", description: "<script>alert(1)</script>")
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task AccountUpdateProfileImage_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            using (var image = TestUtils.CreateDummyImage())
-            using (var media = new MemoryImageMediaItem(image))
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUser>(
-                        new Uri("account/update_profile_image.json", UriKind.Relative),
-                        new Dictionary<string, string> {
+            using var image = TestUtils.CreateDummyImage();
+            using var media = new MemoryImageMediaItem(image);
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUser>(
+                    new Uri("account/update_profile_image.json", UriKind.Relative),
+                    new Dictionary<string, string>
+                    {
                             { "include_entities", "true" },
                             { "include_ext_alt_text", "true" },
                             { "tweet_mode", "extended" },
-                        },
-                        new Dictionary<string, IMediaItem> { { "image", media } })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUser()));
+                    },
+                    new Dictionary<string, IMediaItem> { { "image", media } })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUser()));
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.AccountUpdateProfileImage(media)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
+            await twitterApi.AccountUpdateProfileImage(media)
+                .IgnoreResponse();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task ApplicationRateLimitStatus_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterRateLimits>(
-                        new Uri("application/rate_limit_status.json", UriKind.Relative),
-                        null,
-                        "/application/rate_limit_status")
-                )
-                .ReturnsAsync(new TwitterRateLimits());
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterRateLimits>(
+                    new Uri("application/rate_limit_status.json", UriKind.Relative),
+                    null,
+                    "/application/rate_limit_status")
+            )
+            .ReturnsAsync(new TwitterRateLimits());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.ApplicationRateLimitStatus()
-                    .ConfigureAwait(false);
+            await twitterApi.ApplicationRateLimitStatus();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
         public async Task Configuration_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetAsync<TwitterConfiguration>(
-                        new Uri("help/configuration.json", UriKind.Relative),
-                        null,
-                        "/help/configuration")
-                )
-                .ReturnsAsync(new TwitterConfiguration());
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterConfiguration>(
+                    new Uri("help/configuration.json", UriKind.Relative),
+                    null,
+                    "/help/configuration")
+            )
+            .ReturnsAsync(new TwitterConfiguration());
 
-                twitterApi.apiConnection = mock.Object;
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                await twitterApi.Configuration()
-                    .ConfigureAwait(false);
+            await twitterApi.Configuration();
 
-                mock.VerifyAll();
-            }
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task MediaUpload_Test()
+        public async Task MediaUploadInit_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            using (var image = TestUtils.CreateDummyImage())
-            using (var media = new MemoryImageMediaItem(image))
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostLazyAsync<TwitterUploadMediaResult>(
-                        new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
-                        null,
-                        new Dictionary<string, IMediaItem> { { "media", media } })
-                )
-                .ReturnsAsync(LazyJson.Create(new TwitterUploadMediaResult()));
-
-                twitterApi.apiConnection = mock.Object;
-
-                await twitterApi.MediaUpload(media)
-                    .IgnoreResponse()
-                    .ConfigureAwait(false);
-
-                mock.VerifyAll();
-            }
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUploadMediaInit>(
+                    new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
+                    new Dictionary<string, string>
+                    {
+                            { "command", "INIT" },
+                            { "total_bytes", "123456" },
+                            { "media_type", "image/png" },
+                            { "media_category", "dm_image" },
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUploadMediaInit()));
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.MediaUploadInit(totalBytes: 123456L, mediaType: "image/png", mediaCategory: "dm_image")
+                .IgnoreResponse();
+
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task MediaMetadataCreate_Test()
+        public async Task MediaUploadAppend_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.PostJsonAsync(
-                        new Uri("https://upload.twitter.com/1.1/media/metadata/create.json", UriKind.Absolute),
-                        "{\"media_id\": \"12345\", \"alt_text\": {\"text\": \"hogehoge\"}}")
-                )
-                .Returns(Task.FromResult(0));
-
-                twitterApi.apiConnection = mock.Object;
-
-                await twitterApi.MediaMetadataCreate(mediaId: 12345L, altText: "hogehoge")
-                    .ConfigureAwait(false);
-
-                mock.VerifyAll();
-            }
+            using var image = TestUtils.CreateDummyImage();
+            using var media = new MemoryImageMediaItem(image);
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostAsync(
+                    new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
+                    new Dictionary<string, string>
+                    {
+                            { "command", "APPEND" },
+                            { "media_id", "11111" },
+                            { "segment_index", "1" },
+                    },
+                    new Dictionary<string, IMediaItem> { { "media", media } })
+            )
+            .Returns(Task.CompletedTask);
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.MediaUploadAppend(mediaId: 11111L, segmentIndex: 1, media: media);
+
+            mock.VerifyAll();
         }
 
         [Fact]
-        public async Task UserStreams_Test()
+        public async Task MediaUploadFinalize_Test()
         {
-            using (var twitterApi = new TwitterApi())
-            {
-                var mock = new Mock<IApiConnection>();
-                mock.Setup(x =>
-                    x.GetStreamingStreamAsync(
-                        new Uri("https://userstream.twitter.com/1.1/user.json", UriKind.Absolute),
-                        new Dictionary<string, string> {
-                            { "replies", "all" },
-                            { "track", "OpenTween" },
-                        })
-                )
-                .ReturnsAsync(new MemoryStream());
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostLazyAsync<TwitterUploadMediaResult>(
+                    new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
+                    new Dictionary<string, string>
+                    {
+                            { "command", "FINALIZE" },
+                            { "media_id", "11111" },
+                    })
+            )
+            .ReturnsAsync(LazyJson.Create(new TwitterUploadMediaResult()));
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.MediaUploadFinalize(mediaId: 11111L)
+                .IgnoreResponse();
+
+            mock.VerifyAll();
+        }
 
-                twitterApi.apiConnection = mock.Object;
+        [Fact]
+        public async Task MediaUploadStatus_Test()
+        {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.GetAsync<TwitterUploadMediaResult>(
+                    new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
+                    new Dictionary<string, string>
+                    {
+                            { "command", "STATUS" },
+                            { "media_id", "11111" },
+                    },
+                    null)
+            )
+            .ReturnsAsync(new TwitterUploadMediaResult());
+
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
+
+            await twitterApi.MediaUploadStatus(mediaId: 11111L);
+
+            mock.VerifyAll();
+        }
 
-                var stream = await twitterApi.UserStreams(replies: "all", track: "OpenTween")
-                    .ConfigureAwait(false);
+        [Fact]
+        public async Task MediaMetadataCreate_Test()
+        {
+            var mock = new Mock<IApiConnectionLegacy>();
+            mock.Setup(x =>
+                x.PostJsonAsync(
+                    new Uri("https://upload.twitter.com/1.1/media/metadata/create.json", UriKind.Absolute),
+                    """{"media_id": "12345", "alt_text": {"text": "hogehoge"}}""")
+            )
+            .ReturnsAsync("");
 
-                stream.Dispose();
+            using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
+            twitterApi.ApiConnection = mock.Object;
 
-                mock.VerifyAll();
-            }
-        }
+            await twitterApi.MediaMetadataCreate(mediaId: 12345L, altText: "hogehoge");
 
-        [Theory]
-        [InlineData("", "")]
-        [InlineData("123ABCabc", "123ABCabc")]
-        [InlineData(@"\", @"\\")]
-        [InlineData("\"", "\\\"")]
-        [InlineData("\n", @"\u000A")]
-        [InlineData("\U0001D11E", @"\uD834\uDD1E")]
-        public void EscapeJsonString_Test(string targetText, string expectedText)
-        {
-            Assert.Equal(expectedText, TwitterApi.EscapeJsonString(targetText));
+            mock.VerifyAll();
         }
     }
 }