2014-06-20 3 views
1

"개체 참조가 개체의 인스턴스로 설정되어 있지 않습니다"얻을 수 있지만 내 테스트를 실행하려고합니다. 이견있는 사람? 나는 Moq을 사용하고있다.이상한 "개체 참조가 개체의 인스턴스로 설정되지 않았습니다."오류 Moq 사용 중 오류

시험 방법 :

 // Arrange 
    Mock<ICustomerRepository> CustomerRepo = new Mock<ICustomerRepository>(); 
    Customer NewCustomer = new Customert() { ID = 123456789, Date = DateTime.Now }; 
    CustomerRepo.Setup(x => x.Add()).Returns(NewCustomer); 
    var Controller = new CustomerController(CustomerRepo.Object, new Mock<IProductRepository>().Object); 

    // Act 
    IHttpActionResult actionResult = Controller.CreateCustomer(); 

CreateCustomer 방법 : 당신이 MOQ을 설정하면

 Customer NewCustomer = CustomerRepository.Add(); 

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

당신이 디버깅 할 때, 어떤 객체가 null? Request 객체를 설정 했습니까? –

+0

creatcustomer 메소드의 NewCustomer 객체는 testmethod에 설정된 ID와 날짜로 채워집니다. – user3754602

+0

디버그 모드로 테스트를 실행하면 NewCustomer와 Request가 null이 아니십니까? Moq를 사용할 때 당신은 당신의 요청 객체를 포함하여 HttpContext를 설정해야합니다. –

답변

3

, 그렇지 않으면 요청이 null이 될 것입니다, 또한 당신의 HttpContext를 구성해야합니다. ,

/// <summary> 
/// A Class to allow simulation of SessionObject 
/// </summary> 
public class MockHttpSession : HttpSessionStateBase 
{ 
    Dictionary<string, object> m_SessionStorage = new Dictionary<string, object>(); 

    public override object this[string name] 
    { 
     get { 
      try 
      { 
       return m_SessionStorage[name]; 
      } 
      catch (Exception e) 
      { 
       return null; 
      } 
     } 
     set { m_SessionStorage[name] = value; } 
    } 

} 

public class RequestParams : System.Collections.Specialized.NameValueCollection 
{ 
    Dictionary<string, string> m_SessionStorage = new Dictionary<string, string>(); 

    public override void Add(string name, string value) 
    { 
     m_SessionStorage.Add(name, value); 
    } 

    public override string Get(string name) 
    { 
     return m_SessionStorage[name]; 
    } 

} 

public class MockServer : HttpServerUtilityBase 
{ 
    public override string MapPath(string path) 
    { 

     return @"C:\YourCodePathTowherever\" + path; 
    } 
} 

마지막 :

private Mock<ControllerContext> GetContextBase() 
{ 
    var fakeHttpContext = new Mock<HttpContextBase>(); 
    var request = new Mock<HttpRequestBase>(); 
    var response = new Mock<HttpResponseBase>(); 
    var session = new MockHttpSession(); 
    var server = new MockServer(); 
    var parms = new RequestParams(); 
    var uri = new Uri("http://TestURL/Home/Index"); 

    var fakeIdentity = new GenericIdentity("DOMAIN\\username"); 
    var principal = new GenericPrincipal(fakeIdentity, null); 

    request.Setup(t => t.Params).Returns(parms); 
    request.Setup(t => t.Url).Returns(uri); 
    fakeHttpContext.Setup(t => t.User).Returns(principal); 
    fakeHttpContext.Setup(ctx => ctx.Request).Returns(request.Object); 
    fakeHttpContext.Setup(ctx => ctx.Response).Returns(response.Object); 
    fakeHttpContext.Setup(ctx => ctx.Session).Returns(session); 
    fakeHttpContext.Setup(ctx => ctx.Server).Returns(server); 

    var controllerContext = new Mock<ControllerContext>(); 
    controllerContext.Setup(t => t.HttpContext).Returns(fakeHttpContext.Object); 

    return controllerContext; 
} 

지지 클래스의 라인을 따라 있습니다 : 당신은 당신이 당신의 테스트 케이스의 시작 부분에 전화 컨트롤러의 기능에 뭔가를을 설정할 수 있습니다 :)

작업을

// Arrange 
HomeController controller = new HomeController(); 
controller.ControllerContext = GetContextBase().Object; 

당신에게 Request 객체를 줄 것이다 : 당신의 시험 방법의 상단에, 그냥이 호출을 추가 당신이해야

[편집]

이름 공간은 다음과 같습니다

using System.Security.Principal; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using Moq; 
+0

Thx. 필요한 네임 스페이스를 말할 수 있습니까? – user3754602

+0

thx again. 마지막으로 한 줄에이 오류가 "인식 할 수없는 이스케이프 시퀀스"로 표시됩니다. var fakeIdentity = new GenericIdentity ("DOMAIN \ username"); – user3754602

+0

테스트 사용자 이름을 빼 냈습니다. 도메인 \\ 사용자 이름에 이중 백 슬래시 이스케이프가 포함되어야합니다. 나는 그 대답을 편집했다. –

관련 문제