I'm new at Unit test and try to add a dependency injection for Server.MapPath, this is what I have so far...
IPathMapper
public interface IPathMapper
{
string MapPath(string relativePath);
}
ServerPathMapper
public class ServerPathMapper : IPathMapper
{
public string MapPath(string relativePath)
{
return HttpContext.Current.Server.MapPath(relativePath);
}
}
DummyPathMapper
public class DummyPathMapper : IPathMapper
{
public string MapPath(string relativePath)
{
return "C:/temp/" relativePath;
}
}
Test
[Fact]
public void Add_InvoiceViewModel_ToUploadActionResult()
{
// Arrange
var serverPathMapper = new DummyPathMapper();
var myController = new InvoiceController();
var mockClaim = new Claim("Administrator", "test");
var identity = Substitute.For<ClaimsIdentity>();
identity.Name.Returns("test name");
identity.IsAuthenticated.Returns(true);
identity.FindFirst(Arg.Any<string>()).Returns(mockClaim);
var claimsPrincipal = Substitute.For<ClaimsPrincipal>();
claimsPrincipal.HasClaim(Arg.Any<string>(), Arg.Any<string>()).Returns(true);
claimsPrincipal.HasClaim(Arg.Any<Predicate<Claim>>()).Returns(true);
claimsPrincipal.Identity.Returns(identity);
var httpContext = Substitute.For<HttpContextBase>();
httpContext.User.Returns(claimsPrincipal);
var controllerContext = new ControllerContext(
httpContext, new System.Web.Routing.RouteData(), myController);
myController.ControllerContext = controllerContext;
myController._pathMapper = new DummyPathMapper();
var model = new InvoiceViewModel
{
InvoiceInfoNotice = "",
InvoiceList = new List<Bill>()
};
var constructorInfo = typeof(HttpPostedFile).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0];
var obj = (HttpPostedFile)constructorInfo
.Invoke(new object[] { @"D:\file.xlsx", "application/vnd.ms-excel", null });
model.MembershipRegisterFile = new HttpPostedFileWrapper(obj);
// Act
var actionResult = myController.Upload(model, "");
// Assert
actionResult.Should().NotBeNull();
}
Where and how Do I add the DummyPathMapper in Arrange?
UPDATE: I added this, is this the correct way?
Controller
public IPathMapper _pathMapper;
public InvoiceController()
{
_pathMapper = new ServerPathMapper();
}
CodePudding user response:
IPathMapper
should be injected into the controller as an explicit dependency via constructor injection.
//...
private readonly IPathMapper pathMapper;
//ctor
public InvoiceController(IPathMapper pathMapper) {
this.pathMapper = pathMapper;
}
//...
Assuming DI is being used in your application and it has been configured correctly, then ServerPathMapper
will be injected at run-time.
This will now allow for the test to be arranged accordingly
//...
// Arrange
var serverPathMapper = new DummyPathMapper();
var myController = new InvoiceController(serverPathMapper);
//...