【问题标题】:IHttpActionResult variable passing null in test methodIHttpActionResult 变量在测试方法中传递 null
【发布时间】:2014-06-22 00:29:14
【问题描述】:

我正在为 IHttpActionresult 控制器编写测试方法。 ActionResult 不是 NULL 并且包含所需的数据 (Customer.ID = 986574123)。然而,在第二行中,变量 CreatedResult 为空。我希望它将适当的数据返回给 CreatedResult。我也在使用 Moq 框架。不知道这是否重要。有什么想法吗?如果您需要来自 ActionResult 的更多数据,请在下面发表评论。谢谢。

测试方法代码:

        var CustomerRepository = new Mock<ICustomerRepository>();

        CustomerRepository.Setup(x => x.Add()).Returns(new Customer { ID = 986574123, Date = DateTime.Now});      

        var Controller = new CustomerController(CustomerRepository.Object, new Mock<IProductRepository>().Object);
        var config = new HttpConfiguration();
        var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:38306/api/CreateCustomer");
        var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}");
        var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "Customers" } });
        Controller.ControllerContext = new HttpControllerContext(config, routeData, request);
        Controller.Request = request;
        Controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;

        IHttpActionResult ActionResult = Controller.CreateCustomer();
        // Null occurs here
        var CreatedResult = ActionResult as CreatedAtRouteNegotiatedContentResult<Customer>;

CreateCustomer 添加方法:

         [Route("api/createcustomer")]
         [HttpPost]
         public IHttpActionResult CreateCustomer()
         {
             Customer NewCustomer = CustomerRepository.Add();

             return Created(Request.RequestUri + "/" + NewCustomer.ID.ToString(), new { customerID = NewCustomer.ID });
         }

动作结果数据:

-       Location    {http://localhost:38306/api/createcustomer/986574123}   System.Uri
        AbsolutePath    "/api/createcustomer/986574123" string
        AbsoluteUri "http://localhost:38306/api/createcustomer/986574123"   string
        Authority   "localhost:38306"   string
        DnsSafeHost "localhost" string
        Fragment    ""  string
        Host    "localhost" string
        HostNameType    Dns System.UriHostNameType
        IsAbsoluteUri   true    bool
        IsDefaultPort   false   bool
        IsFile  false   bool
        IsLoopback  true    bool
        IsUnc   false   bool
        LocalPath   "/api/createCustomer/986574123" string
        OriginalString  "http://localhost:38306/api/createcustomer/986574123"   string
        PathAndQuery    "/api/createCustomer/986574123" string
        Port    38306   int
        Query   ""  string
        Scheme  "http"  string
+       Segments    {string[4]} string[]
        UserEscaped false   bool
        UserInfo    ""  string

【问题讨论】:

标签: c# unit-testing moq asp.net-web-api2 actionmethod


【解决方案1】:

让你的测试通过的最简单的改变就是改变这一行

return Created(Request.RequestUri + "/" + NewCustomer.ID.ToString(), new { customerID = NewCustomer.ID });

到下面

return Created(Request.RequestUri + "/" + NewCustomer.ID.ToString(), NewCustomer);

问题是您的 CreatedAtRouteNegotiatedContentResult 的类型参数不是您所期望的。您尝试将result 转换为CreatedAtRouteNegotiatedContentResult&lt;Customer&gt;,而实际上它的类型是CreatedAtRouteNegotiatedContentResult&lt;AnonymousType#1&gt;,因此转换失败并返回null

原因是ApiController的Create(String, T)方法返回了一个CreatedAtRouteNegotiatedContentResult,其类型参数T是你传入的content的类型,而你传入的是anonymous type


您希望使用匿名类型仅返回模型中的某些字段,但您还希望在声明它的上下文之外(即在您的单元测试中)引用此类型。这是不可能的,请参阅上面关于匿名类型的链接 (If you must store query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.)

因此,如果您只想返回某些字段,则需要为此创建特定的视图模型。

class CustomerDetails
{
     public int customerID { get; set; }
}

然后在你的操作方法中

return Created(Request.RequestUri + "/" + NewCustomer.ID.ToString(), new CustomerDetails { customerID = NewCustomer.ID });

【讨论】:

  • 好的,我添加了更多信息。需要满足哪些条件?
  • @user3754602 我根据您提供的新信息更新了我的答案。
  • 谢谢。有没有办法返回类似“new { customerID = NewCustomer.ID }”的东西?我不想将所有客户数据发回给客户端,我希望将 JSON 变量命名为 customerID
  • 有没有办法将 AnonymousType 转换为 Customer?然后通过 CreatedAtRouteNegotiatedContentResult 传递?
  • @user3754602 您不能将匿名类型转换为 Object 以外的任何类型(MSDN 文档说明了这一点)。请参阅我的答案以获取另一种可能的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-11
  • 1970-01-01
  • 2017-04-20
  • 2012-11-22
相关资源
最近更新 更多