【问题标题】:How to unit-test this method?如何对这种方法进行单元测试?
【发布时间】:2015-04-08 12:58:01
【问题描述】:

我有一个方法,这也是我要为其编写测试的方法:

public IPlayerResponse GetPlayerStats(IPlayerRequest playerRequest)
{
    string playerId = playerRequest.PlayerId;

    string requestUri = playerId + "/evaluate";

     var request = new HttpRequestMessage(HttpMethod.Post, requestUri)
                                {
                                    Content = new StringContent
            (JsonConvert.SerializeObject(playerRequest),
             System.Text.Encoding.UTF8,
            "application/json")
          };

      var response = _client
    .SendAsync(request, CancellationToken.None)
    .Result;
     var responseContent = response.
    Content
    .ReadAsStringAsync()
    .Result;



    var playerResponseModel =    
    JsonConvert.DeserializeObject<PlayerResponseModel>(responseContent);
    var playerResponse = _mapper
.Map<IPlayerResponse>(playerResponseModel);

return playerResponse;
 }

请求接口:

public interface IPlayerRequest
    {
        IEnumerable<IPlayerStatsItem> Items { get; set; }
        string PlayerId { get; set; }
    }

我计划为此方法编写一个测试并发送IPlayerRequest 的示例数据,以获取针对已部署端点的响应。我已准备好 TestSetup 以访问端点。

模拟IPlayerRequest 并用一些数据填充它以获得响应的理想方法是什么?

【问题讨论】:

    标签: c# unit-testing .net-4.5 moq mstest


    【解决方案1】:

    还有另一种语法 (Moq functional specifications) 用于为此类情况设置模拟:

    var mockRequest = Mock.Of<IPlayerRequest>(
        r =>
        r.PlayerId == "MOCKID" &&
        r.Items == new List<IPlayerStatsItem>()); //or whatever needed);
    

    还有Mocks.Of&lt;T&gt;,所以你可以用r.Items == Mocks.Of&lt;IPlayerStatsItem&gt;()代替r.Items == new List。这将产生无限的模拟列表。

    【讨论】:

      【解决方案2】:

      在测试设置中的调用方法中创建一个私有类。

      private class PlayerRequest : IPlayerRequest
      {
          //hard code your test values you are passing in
          public string Name {get; private set;}
          public PlayerRequest() {
               Name = "MockName";
          }
      }
      

      然后调用:

      var response = obj.GetPlayerStatus(new PlayerRequest());
      

      已编辑以添加最小起订量版本(如果这是您尝试使用的版本):

      var mockRequest = new Mock<IPlayerRequest>();
      mockRequest.SetupGet(pr => pr.Name).Returns("MOCKNAME");
      
      var response = obj.GetPlayerStatus(mockRequest.Object);
      

      【讨论】:

        【解决方案3】:

        我缺乏将模拟框架用作 Moq 或 RhinoMocks 的经验,在 MS fakes 上的一些东西,对于存根(模拟)和填充效果很好

        如果你有 Visual Studio Premium 或 Ultimate,你总是可以使用 MS fakes! (https://msdn.microsoft.com/en-us/library/hh549175.aspx)

        只需使用存根替换您尝试替换的接口,帖子中对此进行了说明。

        然后你可以按如下方式使用它:

        [TestMethod]
        public void TestSomething()
        {
            // Arrange
            // Stub for PlayerRequest
            StubIPlayerRequest playerRequest = new StubIPlayerRequest
            {
                ItemsSetIEnumerableOfIPlayerStatsItem = items => { }, // Setters do nothing in this example.
                ItemsGet = () => new List<StubIPlayerStatsItem>(), // Also stubbed the other interface here, not required.
                PlayerIdGet = () => "Returns a string",
                PlayerIdSetString = s => { }
            };
        
            // Act
        
            // Assert whatever you need.
        }
        

        如果您需要在其中进行单元测试而无需下载库,这是一个非常简单直接的存根和填充框架。

        关于差异的一些有趣的讨论 --> Mock framework vs MS Fakes frameworks

        HTH。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-01
          • 2013-10-17
          • 1970-01-01
          • 1970-01-01
          • 2012-05-30
          • 2021-07-29
          相关资源
          最近更新 更多