Unit test for a CreateUser() method using JustMock lite

Posted on

Problem

I’m new to unit testing and have created a unit test for a create user action method and it’s passing the test. I’m not sure if this is the right way to unit test a create method.

This is my test method:

[TestMethod]
public void Create_User()
{
    Mapper.CreateMap<UserViewModel, User>();

    //Arrange
    var membershipRepository = Mock.Create<IStaticMembershipService>();
    var userMock = Mock.Create<MembershipUser>();
    Mock.Arrange(() => userMock.ProviderUserKey).Returns(1);
    Mock.Arrange(() => membershipRepository.GetUser()).Returns(userMock);
    var UserRepository = Mock.Create<IUserRepository>();

    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write("Creating Streams for Testing");
    writer.Flush();
    stream.Position = 0;
    var mockFile = Mock.Create<HttpPostedFileBase>();
    Mock.Arrange(() => mockFile.ContentType).Returns("application/pdf");
    Mock.Arrange(() => mockFile.FileName).Returns("Test.pdf");
    Mock.Arrange(() => mockFile.InputStream).Returns(stream);
    Mock.Arrange(() => mockFile.ContentLength).Returns(1);
    UserViewModel mockUserViewModel = new UserViewModel { Description = "TestDesc", Title = "Tester", UserId = 1, File = mockFile };

    Mock.Arrange(() => UserRepository.AddUser(Arg.IsAny<User>())).Returns(new OperationStatus{Status = true});
    //Act
    UserController controller = new UserController(UserRepository, membershipRepository);
    RedirectToRouteResult actionResult = (RedirectToRouteResult)controller.Create(mockUserViewModel);

    //Assert
    Assert.AreEqual(actionResult.RouteValues["Action"], "Index");
}

This is the action method:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserViewModel item)
{
    if (ModelState.IsValid)
    {
        var newUser = Mapper.Map<UserViewModel, User>(item);
        //Populates file name and content type to newUser
        UserHelper.PopulateFile(item.File, newUser);

        newUser.UserId = (int)_membershipService.GetUser().ProviderUserKey;

        var opStatus = _UserRepository.AddUser(newUser);
        if (!opStatus.Status)
            throw new System.Web.Http.HttpResponseException(new   HttpResponseMessage(HttpStatusCode.InternalServerError));

        return RedirectToAction("Index");
    }
    else
        return View(item);
}

Any relevant controller info:

private IUserRepository _UserRepository;
private IStaticMembershipService _membershipService;

public UserController(IUserRepository UserRepo, IStaticMembershipService membershipService)
{
    _UserRepository = UserRepo;
    _membershipService = membershipService;
}

IUserRepository:

public interface IUserRepository
{
    List<User> GetAllUsers(int Id);

    OperationStatus AddUser(User newUser);

    User GetUserById(int Id);
}

UserRepository containing definitions of above interfaces:

public List<User> GetAllUsers(int Id)
{
    using (DataContext)
    {
        return DataContext.Users.Where(j => j.Id == Id).ToList();
    }
}

public Journal GetUserById(int Id)
{
    using (DataContext)
        return DataContext.Users.SingleOrDefault(j => j.UserId == Id);
}     

public OperationStatus AddUser(Journal newUser)
{
    var opStatus = new OperationStatus { Status = true };
    try
    {
        using (DataContext)
        {
            newUser.ModifiedDate = DateTime.Now;
            var j = DataContext.Users.Add(newUser);
            DataContext.SaveChanges();
        }
    }
    catch (Exception e)
    {
        //opStatus = OperationStatus.CreateFromException("Error adding user: ", e);
    }

    return opStatus;
}

The test is running fine. I’m just not sure if it’s the right way for unit testing. Please let me know if I’m following the right approach here.

Solution

I think you are not testing everything. The API should create a user but the only thing you assert is the ActionResult

Assert.AreEqual(actionResult.RouteValues["Action"], "Index");

So the method runs and the result is correct. But has it actually created a new user and add it to the repository? How about this operation?

var opStatus = _UserRepository.AddUser(newUser);

IMO you should also check the repository to see whether the API correctly added the new user to it. I don’t know what interfaces the UserRepository might implement but for this

var UserRepository = Mock.Create<IUserRepository>();

assertions like these ones could be appropriate (just examples) or anything else that makes sense for the repository.

Assert.AreEqual(1, UserRepository.Count);
Assert.AreEqual(referenceUser, UserRepository.GetUser(abc));

What if someone had a problem with the repository and commented it out and actually forgot to add #if DEBUG or made any other changes ignoring the status-code?

public ActionResult Create(UserViewModel item)
{
    if (ModelState.IsValid)
    {
        var newUser = Mapper.Map<UserViewModel, User>(item);
        //Populates file name and content type to newUser
        UserHelper.PopulateFile(item.File, newUser);

        newUser.UserId = (int)_membershipService.GetUser().ProviderUserKey;

        // I temporarily disabled the repository because I didn't work for me.
        //var opStatus = _UserRepository.AddUser(newUser);
        //if (!opStatus.Status)
        //    throw new System.Web.Http.HttpResponseException(new   HttpResponseMessage(HttpStatusCode.InternalServerError));

        return RedirectToAction("Index");
    }
    else
        return View(item);
}

The test would still pass but the result would be wrong.

Leave a Reply

Your email address will not be published. Required fields are marked *