Home > Net >  How to write unit test for a builder design pattern?
How to write unit test for a builder design pattern?

Time:08-29

I am using xunit for my unit testing and I am new to unit testing. I have a builder class like below,

public class UserBuilder
{
    private User _user = new User();

    public UserBuilder UserBuilder(IDataBase db) //IDatabase is available in a different Nuget package which I don't have source code access
    {
        this._user.db = db;
    }
    
    public UserBuilder SetName(string name)
    {
        this._user.name = name.ToLower();
    }

    public UserBuilder SetRole(string role)
    {
        this._user.role = role.ToUpper();
    }

   public void Validate()
   {
       if (this._user.name == null)
           throw  new InvalidDataException();
       if (this._user.db.contains(this._user.name)
           throw new InvalidDataException();
       ......
   }

   public User Build()
   {
      this.validate();
      this._user.db.persist();
      return this._user;
}

I would like to unit test the Build(), Validate() and SetName() but I don't have DB details with me and hence, not sure how to override contains and persist steps.

public class UserBuilderTest
{
    [Fact]
    public void Task_SetName_John()
    {
        // Arrange
        // How to Mock the IDatabase?
        var builder = new UserBuilder(FakeDatabase);

        // Act
        var actual = builder.Validate();

        // Assert
        Assert.Throws<InvalidDataException>(action);
    }   
}

Moreover, how can I check if the name is lower case after calling SetName() from the private _user field?

public class UserBuilderTest
{
    [Fact]
    public void Task_SetName_John()
    {
        // Arrange
        // How to Mock the IDatabase?
        var builder = new UserBuilder(FakeDatabase);
        var expected = 'john";

        // Act
        var actual = builder.SetName("John");

        // Assert
        Assert.Equals(expected, actual);
    }   
}

CodePudding user response:

I've used the Moq library for this. https://github.com/moq/moq4

Usage would look something like this:

var mockDatabase = new Mock<IDataBase>();
// Do setups on the mock if necessary
// mockDatabase.Setup( m => m.SomeMethodOnTheInterface() ).Returns( new Something() );
var builder = new UserBuilder(mockDatabase.Object);

Update for the additional question about validation of SetName() method:

Since the only method exposed to get the User is the Build() method you would need to leverage that and then verify that the name is what you expect. Something like this:

var mockDatabase = new Mock<IDataBase>();
var builder = new UserBuilder(mockDatabase.Object);
var user = builder.SetName("John Doe").Build();
Assert.AreEqual("john doe", user.Name /* assuming this is a property */ );
  • Related