如何单元测试一个Action方法,该方法接受一个Object的数组并在ASP.Net MVC中返回JsonResult

时间:2016-02-04 01:22:09

标签: c# json asp.net-mvc unit-testing jsonresult

我正在尝试在Visual C# Unit Test项目中编写单元测试。

我传递了一个空的Array Frame 类,并返回一个JSON对象。

    [HttpPost]
    public JsonResult SubmitBowlingScore(Frame[] frames)
    {
        int totalScore= 0;
        var objScore = new EngineService();

        for (int i = 0; i < frames.Length; i++)
        {
            Boolean wasSpare = false;

            if (i > 0 && objScore.IsSpare(frames[i-1]))
            {
                wasSpare = true;
            }
            totalScore += objScore.CalculateScore(frames[i], wasSpare);
        }

        return Json("{\"score\":"+ totalScore + "}");
    }

希望使用以下条目进行测试:但不知道如何!!!

 [{""1stRoll"":2,""2ndRoll"":2 ,""3rdRoll"":0},
  {""1stRoll"":4,""2ndRoll"":8 ,""3rdRoll"":0},
  {""1stRoll"":6,""2ndRoll"":2 ,""3rdRoll"":0}];

任何帮助/想法/建议都将受到以下单元测试的赞赏。 SubmitBowlingScore()如何将 Frame [] 数据作为参数?

    [TestMethod]
    public void SubmitBowlingScore()
    {
        //Arrange
        HomeController controller = new HomeController();
        //Act
        JsonResult result = controller.SubmitBowlingScore(**What goes here???**) as JsonResult;

        //Assert
        Assert.IsNotNull(JsonResult, "No JsonResult returned from action method.");
        Assert.AreEqual(@"{[{""1stRoll"":""2"",""2ndRoll"":2 ,""3rdRoll"":0},{""1stRoll"":""2"",""2ndRoll"":8 ,""3rdRoll"":0},{""1stRoll"":""6"",""2ndRoll"":2 ,""3rdRoll"":0}],""Count"":3,""Success"":true}",
               result.Data.ToString());
    }

1 个答案:

答案 0 :(得分:0)

您正在将业务逻辑与表示逻辑混合在一起。您应该将控制器方法的整个主体移动到基于帧计算分数的对象。一旦你有了这个,就没有什么东西可以在控制器中测试(除非你不信任MVC框架......)

我的 Frame 模型的演绎:

public class Frame
{
    public int FirstRoll { get; set; }
    public int SecondRoll { get; set; }
    public int ThirdRoll { get; set; }
}

以下是业务逻辑作为扩展。您可能希望将其分解为自己的类,或者可能使其成为 EngineService 类的成员。

public static class FrameExtensions
{
    public static int SumFrameScores(this Frame[] frames)
    {
        //break out early if no frames have been recorded
        if (frames.Length == 0) return 0;

        int totalScore = 0;
        var objScore = new EngineService();

        for (int i = 0; i < frames.Length; i++)
        {
            bool wasSpare = objScore.IsSpare(frames[i - 1]);
            totalScore += objScore.CalculateScore(frames[i], wasSpare);
        }

        return totalScore;
    }
}

当您进行测试时,您可以直接针对您的C#类/类型进行测试,因此您不必担心JSON /表示层数据转换。

[TestMethod]
public void SubmitBowlingScore()
{
    //Arrange
    var frames = new Frame[]
    {
            new Frame {FirstRoll = 2, SecondRoll = 2, ThirdRoll = 0},
            new Frame {FirstRoll = 2, SecondRoll = 6, ThirdRoll = 0},
            new Frame {FirstRoll = 0, SecondRoll = 9, ThirdRoll = 0}
    };
    //Act
    var score = frames.SumFrameScores();

    //Assert
    Assert.AreEqual(21, score);
}

最后,您的控制器将缩减为以下内容:

[HttpPost]
public JsonResult SubmitBowlingScore(Frame[] frames)
{
    var finalScore = frames.SumFrameScores();
    return Json(new { score = finalScore });
}