简体   繁体   中英

Writing unit test for business logic in c#

I am currently learning c# and need to write unit tests for a business logic layer written by another dev. The method I need to test is a Get method that retrieves a single object from our db. However I am unsure how to do it as I dont have much experience with c# and cant find any examples online.

Here is the data access method:

    public void CreateUser(string userName, int phoneNumber, int age)
    {
        using MySqlCommand mySqlCommand = new MySqlCommand("usp_CreateUser");
        mySqlCommand.CommandType = CommandType.StoredProcedure;
        mySqlCommand.Parameters.AddWithValue("UserName", userName);
        mySqlCommand.Parameters.AddWithValue("TailLength", iconSize);
        mySqlCommand.Parameters.AddWithValue("IconSize", tailLength);

        ExecuteNonQuery(mySqlCommand);
    }

    public UserSettings UpdateUser(string userName, User user)
    {
        if (GetUser(userName) == null)
            return null;

        using MySqlCommand updateCommand = new("usp_UpdateUserByUserName");
        updateCommand.CommandType = CommandType.StoredProcedure;
        updateCommand.Parameters.AddWithValue("userName", userName);
        updateCommand.Parameters.AddWithValue("phoneNumber", userSetting.PhoneNumber);
        updateCommand.Parameters.AddWithValue("age", userSetting.Age);
        ExecuteNonQuery(updateCommand);
        
        return GetUserSetting(userName);
    }

The actual model for a user:

public class User
{
    public int? PhoneNumber { get; set; }
    public int? Age { get; set; }
}

Now the business logic itself:

    public User GetUser(string userName)
    {
        var userSetting = _userDataAccess.GetUser(userName);
        if(user == null)
        {
            _userDataAccess.CreateUser(userName, AppSettings.GetCurrentSettings().PhoneNumber, AppSettings.GetCurrentSettings().Age);
            user = _userDataAccess.GetUser(userName);
        }
        return user;
    }

    public User UpdateUser(string userName, User user)
    {
        var updatedUser = _userDataAccess.UpdateUser(userName, user);
        if (updatedUser == null)
        {
            throw new HttpNotFoundException("User does not exist");
        }
        return updatedUser;
    }

So I am trying to write tests for both these methods and I'm not sure how to do so. I have tried to do the following:

public class BusinessLogicTests
{
    private Mock<IUserDataAccess> _mockDataAccess;

    private UserBusinessLogic _userBusinessLogic;
    private User user;

    public BusinessLogicTests()
    {
        _mockDataAccess = new Mock<IUserDataAccess>();
        _userBusinessLogic = new UserBusinessLogic(_mockDataAccess.Object);

        user = new User()
        {
            PhoneNumber = 1,
            Age = 1
        };
    }

    [Test]
    public void GetUserShouldReturnUser()
    {
        _mockDataAccess.Setup(g => g.CreateUser("test", 1, 1));
        //Arrange
        User user = _userBusinessLogic.GetUser("test");

        Assert.NotNull(user);
    }

But this returns null when it should return a user and therefore Not Null.

Any help will be appreciated

Up to now, the code contains a setup for CreateUser , but not a setup for GetUser . As you want to test that CreateUser is called, you need to setup GetUser in a way that for the first call returns null, but the second returns the created user. You can achieve this with SetupSequence :

[Test]
public void GetUserShouldReturnUser()
{
    // Arrange
    var createdUser = new User() {};
    _mockDataAccess.Setup(g => g.CreateUser("test", 1, 1));
    _mockDataAccess.SetupSequence(g => g.GetUser("test"))
        .Returns((User)null)
        .Returns(createdUser);
    // Act
    User user = _userBusinessLogic.GetUser("test");
    // Assert
    Assert.NotNull(user);
    Assert.Same(createdUser, user);
}

As a sidenote: the code in its current form is prone to race conditions. If the method is called twice, it might attempt to create the same user twice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM